﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "FamStructureTemplateUtility.h"
#include "FamilyConstraintUtils.h"
#include "FamilyConstraintReferenceType.h"
#include "IFamilySketchPlane.h"
#include "IFamily2DSketchArc.h"
#include "IFamily2DSketchEllipse.h"
#include "IFamilyAngleConstraint.h"
#include "IFamilyDiameterConstraint.h"
#include "IFamilyDistanceRatioConstraint.h"
#include "FamilyDocumentUtility.h"
#include "IFamilyExtrusion.h"
#include "IFamilyManager.h"
#include "IFamilyMultiDistanceDimension.h"
#include "IFamilyPlaneSplitForm.h"
#include "IFamilySlopedExtrusion.h"
#include "FamStructureTemplateDocument.h"
#include "IFamilySweep.h"
#include "IFamilySweptLoft.h"
#include "FamilyUtils.h"
#include "GbmpBuiltInParameterDefinitionsNew.h"
#include "GbmpBuiltInParameterStaticVauleListItems.h"
#include "IArc2d.h"
#include "IEllipse2d.h"
#include "IFamilyConfigElement.h"
#include "IGraphicsBRepFace.h"
#include "IInstance.h"
#include "ILine2d.h"
#include "IOnePointInstanceInput.h"
#include "IParameter.h"
#include "IPlane.h"
#include "IPolyCurve.h"
#include "IPublishConfig.h"
#include "IRegenerator.h"
#include "InstancePlacementTypes.h"
#include "IInstanceType.h"
#include "NdbDocUpgradeManager.h"
#include "IParameterDefinitionLibrary.h"
#include "IParameterValueBool.h"
#include "IParameterValueCurveByPoints.h"
#include "IParameterCustomData.h"
#include "IParameterValueCustom.h"
#include "IParameterValueDouble.h"
#include "IParameterValueInt.h"
#include "IFamilyReferenceLine.h"
#include "ReferencePlaneUtils.h"
#include "Vector3dUtils.h"
#include "UnitUniIdentities.h"
#include "ParameterType.h"
#include "IFamilyExtrusion.h"
#include "IFamilyGeometryConstraint.h"
#include "DebugMode.h"
#include "IGraphicsMaterialManager.h"
#include "IFamilyDistanceConstraint.h"
#include "IFamilySketch2D.h"
#include "IFamily2DSketchLine.h"
#include "IReferencePlane.h"
#include "IElementBasicInformation.h"
#include "GcmpBuiltInParameterDefinitions.h"
#include "BuiltInStructureFamilies.h"
#include "IGenericElement.h"
#include "IParameterValueString.h"
#include "IParameterValueDisplayString.h"
#include "StructureInstanceSecondKeys.h"
#include "IParameterValidator.h"
#include "StructureInstanceSectionShapeType.h"
#include "StructureDefaultFamilyTypes.h"
#include "IFamilyParameterDefinition.h"
#include "GbmpBuiltInCategoryUniIdentitiesNew.h"
#include "IUserTransaction.h"
#include "IEditMode.h"
#include "IDocumentManager.h"
#include "IFamily.h"
#include "FilePath.h"
#include "IFileExtensions.h"
#include "IElementParameters.h"
#include "FamilySolverUtils.h"
#include "FamilySolverResult.h"
#include "IElementParameterBindings.h"
#include "SectionShapeType.h"
#include "IFamilyAlignConstraint.h"
#include "IModelView.h"
#include "Coordinate3d.h"
#include "GbmpConstants.h"
#include "GmArchitectureFamilyUtils.h"
#include "FamilyBuiltInParameterDefinitions.h"
#include "GbmpModelViewUtil.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

CREATE_DEBUG_MODE_EXPORT(RotateFaceTexture, L"旋转面贴图", gcmp::DebugModeGroup::DMGT_OTHERS, L"GDMPLab",
    L"2023-12-20", L"旋转面贴图");

using namespace gcmp;
using namespace gfam;

#define RectBasicBeamExteriorFaceNodeTag                5
#define RectBasicBeamInteriorFaceNodeTag                3
#define RectVariableSectionBeamExteriorFaceNodeTag      6
#define RectVariableSectionBeamInteriorFaceNodeTag      4
#define RectStripFoundationExteriorFaceNodeTag          5
#define RectStripFoundationInteriorFaceNodeTag          3
#define FloorTopFaceNodeTag                             2
#define FloorBottomFaceNodeTag                          1

const double g_dRefPlaneDefaultLength = 2250;


#define FAMILY_LEFT_RIGHT_CENTER_REFERENCE_PLANE_NAME GBMP_TR(L"左右中心")
#define FAMILY_TOP_BOTTOM_CENTER_REFERENCE_PLANE_NAME GBMP_TR(L"上下中心")
#define FAMILY_FRONT_BACK_CENTER_REFERENCE_PLANE_NAME GBMP_TR(L"前后中心")

#define FAMILY_LEFT_REFERENCE_PLANE_NAME GBMP_TR(L"左")
#define FAMILY_RIGHT_REFERENCE_PLANE_NAME GBMP_TR(L"右")
#define FAMILY_BACK_REFERENCE_PLANE_NAME GBMP_TR(L"后")
#define FAMILY_FRONT_REFERENCE_PLANE_NAME GBMP_TR(L"前")
#define FAMILY_TOP_REFERENCE_PLANE_NAME GBMP_TR(L"顶")
#define FAMILY_BOTTOM_REFERENCE_PLANE_NAME GBMP_TR(L"底")

#define FAMILY_INNER_REFERENCE_PLANE_NAME GBMP_TR(L"String_Family_Reference_Plane_Interior")
#define FAMILY_OUTER_REFERENCE_PLANE_NAME GBMP_TR(L"String_Family_Reference_Plane_Exterior")
namespace
{
    std::wstring GetBuiltInFamilyPath(const std::wstring& familyName)
    {
        const std::wstring familyFileName = familyName + IDocumentManager::Get()->GetFileExtensions()->GetDefaultFamilyFileExt();
        return FilePath::Combine(LogManager::Get()->GetLogsFolder(), familyFileName);
    }

    IFamilyDistanceConstraint* AddDistanceConstraint(IDocument* pDoc, const Vector3d& dimPos, double dimScale, ElementId sketchId, ElementId sketchPlaneId, const Coordinate3d& coord,
        ElementId element1Id, const GraphicsNodeId& leafTag1, GraphicsNodeReferenceType refType1, ElementId element2Id, const GraphicsNodeId& leafTag2, GraphicsNodeReferenceType refType2)
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

        IFamilyMultiDistanceDimension* pMultiDistDim = IFamilyMultiDistanceDimension::Create(pDoc, dimPos, dimScale, sketchPlaneId, sketchId, coord, false);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pMultiDistDim, L"pMultiDistDim为空",L"GDMPLab",L"2024-03-30");
        OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(element1Id, leafTag1, refType1);
        pMultiDistDim->AddReferenceObject(TransferOwnership(opRef1));
        OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(element2Id, leafTag2, refType2);
        pMultiDistDim->AddReferenceObject(TransferOwnership(opRef2));

        IFamilyDistanceConstraint* pDistanceConstraint = IFamilyDistanceConstraint::Create(pDoc, sketchId, sketchPlaneId, pMultiDistDim->GetOwnerElementId(), coord);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDistanceConstraint, L"pDistanceConstraint为空",L"GDMPLab",L"2024-03-30");
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(element1Id, leafTag1, refType1);
        pDistanceConstraint->AddReferenceObject(TransferOwnership(opRef3));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef4 = IGraphicsNodeReference::Create(element2Id, leafTag2, refType2);
        pDistanceConstraint->AddReferenceObject(TransferOwnership(opRef4));

        pMultiDistDim->AddConstraintObject(pDistanceConstraint->GetOwnerElementId());

        return pDistanceConstraint;
    }

    IFamilyDistanceConstraint* AddDistanceConstraint(IDocument* pDoc, const Vector3d& dimPos, double dimScale, ElementId sketchId, ElementId sketchPlaneId, const Coordinate3d& coord,
        IElement* pEle1, const GraphicsNodeId& leafTag1, GraphicsNodeReferenceType refType1, IElement* pEle2, const GraphicsNodeId& leafTag2, GraphicsNodeReferenceType refType2)
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pEle1 && pEle2, L"pEle1 or pEle2为空",L"GDMPLab",L"2024-03-30");
        return AddDistanceConstraint(pDoc, dimPos, dimScale, sketchId, sketchPlaneId, coord, pEle1->GetElementId(), leafTag1, refType1, pEle2->GetElementId(), leafTag2, refType2);
    }

    IFamilyDistanceRatioConstraint* AddEqualDistanceConstraint(IDocument* pDoc, const Vector3d& dimPos, double dimScale, ElementId sketchId, ElementId sketchPlaneId, const Coordinate3d& coord,
        ElementId element1Id, const GraphicsNodeId& leafTag1, ElementId element2Id, const GraphicsNodeId& leafTag2, ElementId element3Id, const GraphicsNodeId& leafTag3)
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

        IFamilyMultiDistanceDimension* pMultiDistDim = IFamilyMultiDistanceDimension::Create(pDoc, dimPos, FamilyTemplateConst::DimScale, sketchPlaneId, sketchId, coord, true);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pMultiDistDim, L"pMultiDistDim为空",L"GDMPLab",L"2024-03-30");
        OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(element1Id, leafTag1);
        OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(element2Id, leafTag2);
        OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(element3Id, leafTag3);

        Vector3d projDir = Vector3d::Zero; // 默认没有点参与约束，传入空值
        int ratioSign = FamilyConstraintUtils::CalcRatioSign(pDoc, coord, opRef1.get(), opRef2.get(), opRef3.get(), projDir);

        pMultiDistDim->AddReferenceObject(TransferOwnership(opRef1));
        pMultiDistDim->AddReferenceObject(TransferOwnership(opRef2));
        pMultiDistDim->AddReferenceObject(TransferOwnership(opRef3));

        IFamilyDistanceRatioConstraint* pDistEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDoc, sketchId, sketchPlaneId, pMultiDistDim->GetOwnerElementId(), coord);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDistEqualConstraint, L"pDistEqualConstraint为空",L"GDMPLab",L"2024-03-30");
        OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(element1Id, leafTag1);
        pDistEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
        OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(element2Id, leafTag2);
        pDistEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
        OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(element3Id, leafTag3);
        pDistEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));

        pDistEqualConstraint->SetRatioValue(0.5 * ratioSign);
        pMultiDistDim->AddConstraintObject(pDistEqualConstraint->GetOwnerElementId());

        return pDistEqualConstraint;
    }

    IFamilyDistanceRatioConstraint* AddEqualDistanceConstraint(IDocument* pDoc, const Vector3d& dimPos, double dimScale, ElementId sketchId, ElementId sketchPlaneId, const Coordinate3d& coord,
        IElement* pEle1, const GraphicsNodeId& leafTag1, IElement* pEle2, const GraphicsNodeId& leafTag2, IElement* pEle3, const GraphicsNodeId& leafTag3)
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pEle1 && pEle2 && pEle3, L"pEle1 or pEle2 or pEle3为空",L"GDMPLab",L"2024-03-30");
        return AddEqualDistanceConstraint(pDoc, dimPos, dimScale, sketchId, sketchPlaneId, coord, pEle1->GetElementId(), leafTag1, pEle2->GetElementId(), leafTag2, pEle3->GetElementId(), leafTag3);
    }

    IFamilyAngleConstraint* AddAngleConstraint(IDocument* pDoc, ElementId sketchId, ElementId sketchPlaneId, const Coordinate3d& coord,
        IElement* pEle1, const GraphicsNodeId& leafTag1, GraphicsNodeReferenceType refType1, IElement* pEle2, const GraphicsNodeId& leafTag2, GraphicsNodeReferenceType refType2)
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pEle1 && pEle2, L"pEle1 or pEle2为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

        IFamilyAngleConstraint* pAngleConstraint = IFamilyAngleConstraint::Create(pDoc, sketchId, sketchPlaneId, coord);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pAngleConstraint, L"pAngleConstraint为空",L"GDMPLab",L"2024-03-30");

        OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pEle1->GetElementId(), leafTag1, refType1);
        pAngleConstraint->AddReferenceObject(TransferOwnership(opRef1));

        OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pEle2->GetElementId(), leafTag2, refType2);
        pAngleConstraint->AddReferenceObject(TransferOwnership(opRef2));

        return pAngleConstraint;
    }

    // 该矩形未添加对齐到水平面的约束，所以可以旋转
    bool CreateRectangle(IDocument* pDoc, const IFamilySketchPlane* pSketchPlane, const IFamilySketch2D* pSketch, Vector3d vts[4], IFamily2DSketchLine* pFamLine[4])
    {
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc && pSketchPlane && pSketch, L"无效参数",L"GDMPLab",L"2024-03-30");

        for (int i = 0; i < 4; ++i)
        {
            pFamLine[i] = IFamily2DSketchLine::Create(pDoc, pSketch->GetOwnerElementId(), pSketchPlane->GetOwnerElementId(), vts[i], vts[(i + 1) % 4]);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamLine[i], L"pFamLine为空",L"GDMPLab",L"2024-03-30");
        }

        // 首尾相接
        for (int i = 0; i < 4; ++i)
        {
            FamilyConstraintUtils::AddConstraintAsCoincidentPoints(pDoc, pFamLine[i]->GetOwnerElementId(), FamilyConstraintReferenceType::End, pFamLine[(i + 1) % 4]->GetOwnerElementId(), FamilyConstraintReferenceType::Start, pSketchPlane, pSketch);
        }

        // 对边平行
        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::Parallel, pFamLine[0]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pFamLine[2]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);
        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::Parallel, pFamLine[1]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pFamLine[3]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);

        // 邻边垂直
        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::Perpendicular, pFamLine[0]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pFamLine[1]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);

        return true;
    }

    bool CreateProfileT(gcmp::IDocument* pDoc, const IFamilySketchPlane* pSketchPlane, const IFamilySketch2D* pSketch, Vector3d vts[8], IFamily2DSketchLine* pFamLine[8])
    {
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc && pSketchPlane && pSketch, L"无效参数",L"GDMPLab",L"2024-03-30");

        for (int i = 0; i < 8; ++i)
        {
            pFamLine[i] = IFamily2DSketchLine::Create(pDoc, pSketch->GetOwnerElementId(), pSketchPlane->GetOwnerElementId(), vts[i], vts[(i + 1) % 8]);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamLine[i], L"pFamLine为空",L"GDMPLab",L"2024-03-30");
        }

        // 首尾相接
        for (int i = 0; i < 8; ++i)
        {
            FamilyConstraintUtils::AddConstraintAsCoincidentPoints(pDoc, pFamLine[i]->GetOwnerElementId(), FamilyConstraintReferenceType::End, pFamLine[(i + 1) % 8]->GetOwnerElementId(), FamilyConstraintReferenceType::Start, pSketchPlane, pSketch);
        }

        // 对边平行
        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::Parallel, pFamLine[0]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pFamLine[2]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);
        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::Parallel, pFamLine[0]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pFamLine[4]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);
        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::Parallel, pFamLine[0]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pFamLine[6]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);
        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::Parallel, pFamLine[1]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pFamLine[3]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);
        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::Parallel, pFamLine[1]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pFamLine[5]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);
        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::Parallel, pFamLine[1]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pFamLine[7]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);

        // 邻边垂直
        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::Perpendicular, pFamLine[0]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pFamLine[1]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);

        return true;
    }


    gcmp::IReferencePlane* CreateReferencePlaneByPoints(gcmp::IDocument * pDbDoc, const Vector3d& startPt, const Vector3d& endPt, const Vector3d& workPlaneNormal)
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!Vector3dUtils::IsEqual(startPt, endPt, Constants::DOUBLE_EPS), L"无法创建参考平面",L"GDMPLab",L"2024-03-30");

        Vector3d dirX = endPt - startPt;
        dirX.Normalize();

        Vector3d dirY = workPlaneNormal;
        dirY.Normalize();

        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(fabs(dirX.Dot(dirY)) < Constants::DOUBLE_EPS, L"工作平面法向与参考平面不垂直。",L"GDMPLab",L"2024-03-30");

        Vector3d origin = (startPt + endPt) * 0.5;
        Vector3d dirZ = dirX.Cross(dirY);
        dirZ.Normalize();

        double length = (startPt - endPt).Length();
        double startU = -length * 0.5;
        double endU = length * 0.5;
        double startV = -g_dRefPlaneDefaultLength;
        double endV = g_dRefPlaneDefaultLength;

        OwnerPtr<IPlane> pPlane = IPlane::Create(origin, dirZ, Intervald(startU, endU), Intervald(startV, endV));
        gcmp::IReferencePlane* pReferencePlane = gcmp::IReferencePlane::Create(pDbDoc, pPlane.get());
        return pReferencePlane;
    }


    //返回值可能为nullptr
    gcmp::IReferencePlane* GetReferencePlane(const std::vector<gcmp::IReferencePlane *>& vPlanes, const std::wstring& wsName)
    {
        gcmp::IReferencePlane * pReferencePlane = nullptr;
        for (auto iter = vPlanes.begin(); iter != vPlanes.end(); ++iter)
        {
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS((*iter) && (*iter)->GetBasicInformation(), L"(*iter) or (*iter)->GetBasicInformation()为空",L"GDMPLab",L"2024-03-30");
            if ((*iter)->GetBasicInformation()->GetName() == wsName)
            {
                pReferencePlane = *iter;
                break;
            }
        }
        return pReferencePlane;
    }
}

gfam::IFamilyParameterDefinition* FamStructureTemplateUtility::CreateParameterDefination
(
    gcmp::IDocument* pDbDoc,
    const gcmp::UniIdentity& uid,
    bool bIsInstance,
    bool bIsDeterminedByFormula,
    const std::wstring& formula,
    gfam::FamilyParameterType eParameterType
)
{
    DBG_WARN_AND_RETURN_UNLESS(pDbDoc != nullptr, nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");

    gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_UNLESS(pFamilyManager != nullptr, nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    gfam::IFamilyParameterDefinition* pFamParameterDefinition = const_cast<gfam::IFamilyParameterDefinition*>(pFamilyManager->GetFamilyParameterDefinition(uid));
    //只用在初始化类模板时，一定为空；如果用在其他地方，出现不为空的情况，需自行处理
    if (pFamParameterDefinition == nullptr)
    {
        const IParameterDefinition* parameterDefinition = IParameterDefinitionLibrary::Get(pDbDoc)->GetParameterDefinitionByUid(uid);

        DBG_WARN_AND_RETURN_UNLESS(parameterDefinition != nullptr, nullptr, L"parameterDefinition为空",L"GDMPLab",L"2024-03-30");

        gfam::IFamilyParameterDefinition* pNewFamParameterDefinition = gfam::IFamilyParameterDefinition::Create(pDbDoc, parameterDefinition, eParameterType, bIsInstance, formula);
        DBG_WARN_AND_RETURN_UNLESS(pNewFamParameterDefinition != nullptr, nullptr, L"pNewFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");

        bool  result = pFamilyManager->AddFamilyParameterDefinition(pNewFamParameterDefinition);
        DBG_WARN_AND_RETURN_UNLESS(result, nullptr, L"族参数添加失败，已经有同名参数？",L"GDMPLab",L"2024-03-30");

        return pNewFamParameterDefinition;
    }
    else
    {
        return pFamParameterDefinition;//目前框架下，不可能有不为空的情况
    }
}

bool FamStructureTemplateUtility::AddBuiltInParameterDefination(
    gcmp::IDocument* pDbDoc,
    gcmp::OwnerPtr<gcmp::IParameterValueStorage> upParamValue,
    const gcmp::UniIdentity& uid,
    bool bIsInstance,
    bool bIsDeterminedByFormula,
    const std::wstring& formula,
    gcmp::ParameterProcessType ppt,
    gfam::FamilyParameterType eParameterType
)
{
    DBG_WARN_AND_RETURN_UNLESS(nullptr != pDbDoc, false, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    gfam::IFamilyParameterDefinition* pFamParameterDefinition = CreateParameterDefination(pDbDoc, uid, bIsInstance, bIsDeterminedByFormula, formula, eParameterType);
    DBG_WARN_AND_RETURN_UNLESS(pFamParameterDefinition != nullptr, false, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");

    if (pFamParameterDefinition)
    {
        gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
        DBG_WARN_AND_RETURN_UNLESS(pFamilyManager != nullptr, false, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
        const IElementBasicInformation* pElementBasicInformation = pFamParameterDefinition->GetBasicInformation();
        DBG_WARN_AND_RETURN_UNLESS(nullptr != pElementBasicInformation, false, L"pElementBasicInformation为空",L"GDMPLab",L"2024-03-30");
        if (pElementBasicInformation->GetElementUid() != uid) // 要增加的参数已有同名参数
        {
            ElementId oldParamId = pElementBasicInformation->GetElementId();
            pFamilyManager->RemoveFamilyParameterDefinition(pFamParameterDefinition);
            pFamParameterDefinition = CreateParameterDefination(pDbDoc, uid, bIsInstance, bIsDeterminedByFormula, formula, eParameterType);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamParameterDefinition, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
            pElementBasicInformation = pFamParameterDefinition->GetBasicInformation();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pElementBasicInformation, L"pElementBasicInformation为空",L"GDMPLab",L"2024-03-30");
            if (pElementBasicInformation->GetElementUid() != uid)
            {
                return false;
            }

            std::vector<IElement*> vecAllDimConstaint = pDbDoc->GetElementsByCategory(gcmp::BuiltInCategoryUniIdentities::BICU_FAM_CONSTRAINT);
            FOR_EACH(pItem, vecAllDimConstaint)
            {
                IGenericElement* pGenericElement = quick_cast<IGenericElement>(pItem);
                if (!pGenericElement)
                    continue;

                IFamilyDimensionConstraint* pDimConstraint = quick_cast<IFamilyDimensionConstraint>(pGenericElement->GetExternalObject());
                if (pDimConstraint == nullptr)
                    continue;

                if (pDimConstraint->GetFamilyParameterDefinitionId() == oldParamId)
                {
                    pDimConstraint->SetFamilyParameterDefinitionId(pElementBasicInformation->GetElementId());
                }
            }
        }
        else if (uid == PARAMETER_UID(ColumnStructureTypeBuiltInParameter))
        {
            std::vector<OwnerPtr<gcmp::IParameterValueDisplayString>> parameterValueDisplayStrings;
            OwnerPtr<IParameterValueStorage> opStorage1 = IParameterValueString::Create(L"框架柱");
            parameterValueDisplayStrings.emplace_back(IParameterValueDisplayString::CreateParameterValueDisplayString(TransferOwnership(opStorage1), L"框架柱"));
            OwnerPtr<IParameterValueStorage> opStorage2 = IParameterValueString::Create(L"构造柱");
            parameterValueDisplayStrings.emplace_back(IParameterValueDisplayString::CreateParameterValueDisplayString(TransferOwnership(opStorage2), L"构造柱"));
            gcmp::OwnerPtr<gcmp::IParameterValueList> opParameterValueList = IParameterValueList::CreateParameterStaticValueList(uid, parameterValueDisplayStrings);
            if (opParameterValueList)
            {
                pFamParameterDefinition->SetValueList(TransferOwnership(opParameterValueList)); //设置值列表
            }
        }
        else if (uid == PARAMETER_UID(ColumnLayingTypeBuiltInParameter))
        {
            std::vector<OwnerPtr<gcmp::IParameterValueDisplayString>> parameterValueDisplayStrings;
            OwnerPtr<IParameterValueStorage> opStorage1 = IParameterValueString::Create(L"直柱");
            parameterValueDisplayStrings.emplace_back(IParameterValueDisplayString::CreateParameterValueDisplayString(TransferOwnership(opStorage1), L"直柱"));
            OwnerPtr<IParameterValueStorage> opStorage2 = IParameterValueString::Create(L"斜柱");
            parameterValueDisplayStrings.emplace_back(IParameterValueDisplayString::CreateParameterValueDisplayString(TransferOwnership(opStorage2), L"斜柱"));
            gcmp::OwnerPtr<gcmp::IParameterValueList> opParameterValueList = IParameterValueList::CreateParameterStaticValueList(uid, parameterValueDisplayStrings);
            if (opParameterValueList)
            {
                pFamParameterDefinition->SetValueList(TransferOwnership(opParameterValueList)); //设置值列表
            }
        }
        else if (uid == PARAMETER_UID(BeamStructureTypeBuiltInParameter))
        {
            std::vector<OwnerPtr<gcmp::IParameterValueDisplayString>> parameterValueDisplayStrings;
            OwnerPtr<IParameterValueStorage> opStorage1 = IParameterValueString::Create(L"框架梁");
            parameterValueDisplayStrings.emplace_back(IParameterValueDisplayString::CreateParameterValueDisplayString(TransferOwnership(opStorage1), L"框架梁"));
            OwnerPtr<IParameterValueStorage> opStorage2 = IParameterValueString::Create(L"二次结构梁");
            parameterValueDisplayStrings.emplace_back(IParameterValueDisplayString::CreateParameterValueDisplayString(TransferOwnership(opStorage2), L"二次结构梁"));
            gcmp::OwnerPtr<gcmp::IParameterValueList> opParameterValueList = IParameterValueList::CreateParameterStaticValueList(uid, parameterValueDisplayStrings);
            if (opParameterValueList)
            {
                pFamParameterDefinition->SetValueList(TransferOwnership(opParameterValueList)); //设置值列表
            }
        }
        else if (uid == PARAMETER_UID(WallStructureTypeBuiltInParameter))
        {
            std::vector<OwnerPtr<gcmp::IParameterValueDisplayString>> parameterValueDisplayStrings;
            OwnerPtr<IParameterValueStorage> opStorage1 = IParameterValueString::Create(L"剪力墙");
            parameterValueDisplayStrings.emplace_back(IParameterValueDisplayString::CreateParameterValueDisplayString(TransferOwnership(opStorage1), L"剪力墙"));
            OwnerPtr<IParameterValueStorage> opStorage2 = IParameterValueString::Create(L"砌体墙");
            parameterValueDisplayStrings.emplace_back(IParameterValueDisplayString::CreateParameterValueDisplayString(TransferOwnership(opStorage2), L"砌体墙"));
            OwnerPtr<IParameterValueStorage> opStorage3 = IParameterValueString::Create(L"现浇混凝土");
            parameterValueDisplayStrings.emplace_back(IParameterValueDisplayString::CreateParameterValueDisplayString(TransferOwnership(opStorage3), L"现浇混凝土"));
            gcmp::OwnerPtr<gcmp::IParameterValueList> opParameterValueList = IParameterValueList::CreateParameterStaticValueList(uid, parameterValueDisplayStrings);
            if (opParameterValueList)
            {
                pFamParameterDefinition->SetValueList(TransferOwnership(opParameterValueList)); //设置值列表
            }
        }

        pFamilyManager->SetFamilyParameterProcessType(pFamParameterDefinition, ppt);
        pFamilyManager->SetParameterValueStorage(pFamParameterDefinition, TransferOwnership(upParamValue));
        return true;
    }
    else
    {
        return false;
    }
}

bool FamStructureTemplateUtility::AddFamilyParameterDefination(gcmp::IDocument* pDbDoc,
    const std::wstring& name,
    gfam::FamilyParameterType parameterType,
    bool bIsInstance,
    const std::wstring& formula,
    const UniIdentity& unitTypeId,
    const UniIdentity& paramTypeId)
{
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    if (pFamilyManager->GetFamilyParameterDefinition(name))
        return true;

    IFamilyParameterDefinition* pFamilyParameterDefinition = IFamilyParameterDefinition::Create(pDbDoc, name, parameterType, bIsInstance, formula);
    if (unitTypeId.IsValid())
        pFamilyParameterDefinition->SetUnitTypeId(unitTypeId);
    if (paramTypeId.IsValid())
        pFamilyParameterDefinition->SetParameterTypeId(paramTypeId);

    return pFamilyManager->AddFamilyParameterDefinition(pFamilyParameterDefinition);
}
void FamStructureTemplateUtility::InitProfileFamilyDocument(gcmp::IDocument* pDbDoc, bool bIsInPlaceEditMode)
{
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"无法获得FamilyManager",L"GDMPLab",L"2024-03-30");
    const IFamilyParameterDefinition* pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::Profile));

    const IParameterDefinitionLibrary* pParameterDefinitionLibrary = IParameterDefinitionLibrary::Get(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pParameterDefinitionLibrary, L"pParameterDefinitionLibrary为空",L"GDMPLab",L"2024-03-30");

    const IParameterDefinition* parameterDefinition = pParameterDefinitionLibrary->GetParameterDefinitionByUid(PARAMETER_UID(ProfileFamilyProjectAngle));
    DBG_WARN_AND_RETURN_VOID_UNLESS(parameterDefinition, L"parameterDefinition为空",L"GDMPLab",L"2024-03-30");

    IFamilyParameterDefinition* pFamParameterDefinition = IFamilyParameterDefinition::Create(pDbDoc, parameterDefinition, FamilyParameterType::Angle, true, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->AddFamilyParameterDefinition(pFamParameterDefinition);
    pFamilyManager->SetFamilyParameterAsDrive(pFamParameterDefinition, true);
    pFamilyManager->SetParameterValueStorage(pFamParameterDefinition, IParameterValueDouble::Create(0.0));

    std::vector<IElement*> allRefPlanes = pDbDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_REFERENCE_PLANE);
    IReferencePlane* pReferencePlaneBottom = nullptr;
    FOR_EACH(pItem, allRefPlanes)
    {
        IReferencePlane* pRefPlane = quick_cast<IReferencePlane>(pItem);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pRefPlane != nullptr, L"pRefPlane为空",L"GDMPLab",L"2024-03-30");

        if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfTopBottom)
        {
            pReferencePlaneBottom = pRefPlane;
        }
    }
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneBottom, L"参照平面获取失败！",L"GDMPLab",L"2024-03-30");
    // 轮廓草图，XOY面
    Coordinate3d profileSketchCoord(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    IFamilySketchPlane* pProfileSketchPlane = IFamilySketchPlane::Create(pDbDoc, profileSketchCoord);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pProfileSketchPlane, L"轮廓草图平面创建失败",L"GDMPLab",L"2024-03-30");
    IFamilySketch2D* pProfileSketch = IFamilySketch2D::Create(pDbDoc, pProfileSketchPlane->GetOwnerElementId());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pProfileSketch, L"轮廓草图创建失败！",L"GDMPLab",L"2024-03-30");
    pProfileSketchPlane->SetSketchId(pProfileSketch->GetOwnerElementId());
    pProfileSketchPlane->SetReferencePlaneId(pReferencePlaneBottom->GetElementId());

    // 进入草图编辑模式
    IEditMode::Get(pDbDoc, L"SketchModeType")->StartEditing(pDbDoc, pProfileSketch->GetOwnerElementId(), false, false);
}

//轮廓族在用，可以移动位置
std::wstring FamStructureTemplateUtility::CreateBuiltInProfileFamilyDocument(const std::wstring& familyName)
{
    IDocument* pProfileDoc = FamilyDocumentUtility::CreateFamilyDocument(gcmp::BuiltInCategoryUniIdentities::BICU_PROFILE, GBMP_TR(L"系统内置轮廓族"));
    DBG_WARN_AND_RETURN_UNLESS(pProfileDoc != nullptr, L"", L"内置轮廓族创建失败",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IUserTransaction> ut = IUserTransaction::Create(pProfileDoc, GBMP_TR(L"初始化轮廓族相关数据"), true);
    DBG_WARN_AND_RETURN_UNLESS(ut != nullptr, L"", L"ut为空",L"GDMPLab",L"2024-03-30");

    InitProfileFamilyDocument(pProfileDoc, false);
    // 绘制默认草图线
    std::vector<IElement*> profileSketchs = pProfileDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_SKETCH);
    DBG_WARN_AND_RETURN_UNLESS((profileSketchs.size() == 1), L"", L"无法获取Sketch",L"GDMPLab",L"2024-03-30");

    IGenericElement* pGenericElement = quick_cast<IGenericElement>(profileSketchs[0]);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElement, L"pGenericElement为空",L"GDMPLab",L"2024-03-30");

    IFamilySketch2D* pSketch = dynamic_cast<IFamilySketch2D*>(pGenericElement->GetExternalObject());
    DBG_WARN_AND_RETURN_UNLESS(pSketch, nullptr, L"pSketch为空",L"GDMPLab",L"2024-03-30");

    // 进入草图编辑模式。
    //pProfileDoc->SetDocumentEditMode(L"SketchModeType");
    Vector3d centerPt(0, 0, 0);
    IFamily2DSketchArc* pArc = IFamily2DSketchArc::Create(pProfileDoc, pSketch->GetOwnerElementId(), pSketch->GetSketchPlaneId(), centerPt, Vector3d::UnitX, Vector3d::UnitY, 100, 0, gcmp::Constants::MATH_2PI, 1);
    DBG_WARN_AND_RETURN_UNLESS(pArc != nullptr, L"", L"轮廓线创建失败",L"GDMPLab",L"2024-03-30");
    // 退出草图编辑模式。
    //pProfileDoc->SetDocumentEditMode(L"");
    ut->CommitAndResetHistory();
    std::wstring strProfileDocPath = GetBuiltInFamilyPath(familyName);
    DocumentSaveOptions saveOptions(false);
    DocumentSaveResult saveResult;
    pProfileDoc->SaveAs(strProfileDocPath, saveOptions, saveResult);
    DBG_WARN_AND_RETURN_UNLESS(saveResult.Code == DocumentSaveError::Ok, L"", L"Save family failed! ",L"GDMPLab",L"2024-03-30");

    IDocumentManager::Get()->CloseDocument(pProfileDoc->GetRuntimeId());
    return strProfileDocPath;
}

//初始化轮廓族的环境
void FamStructureTemplateUtility::InitFamilyBasedOnProfileFamilyDocument(gcmp::IDocument* pDbDoc, bool bIsInPlaceEditMode)
{
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"无法获得FamilyManager",L"GDMPLab",L"2024-03-30");

    const IFamilyParameterDefinition* pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::FamilyBasedOnProfile));


    std::wstring strProfileDocPath = CreateBuiltInProfileFamilyDocument(GBMP_TR(L"系统内置轮廓族"));
    std::wstring errorMsg;
    IFamily* loadedFamily = quick_cast<IFamily>(FamilyUtils::LoadFamily(pDbDoc, strProfileDocPath, errorMsg, nullptr));
    DBG_WARN_AND_RETURN_VOID_UNLESS(loadedFamily != nullptr, L"loadedFamily为空",L"GDMPLab",L"2024-03-30");
    std::vector<IInstanceType*> instanceTypes = loadedFamily->GetInstanceTypes();
    DBG_WARN_AND_RETURN_VOID_UNLESS(instanceTypes.size() == 1, L"InstanceType 数目不为1",L"GDMPLab",L"2024-03-30");

    pFamilyManager->SetBuiltInProfileInstanceType(instanceTypes[0]->GetElementId());
}

void FamStructureTemplateUtility::InitWallFamilyDocument(IDocument* pDbDoc, bool isVariableSectionWall)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
    const IFamilyParameterDefinition* pCoordDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(CoordinateSystemBuiltInParameter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCoordDef != nullptr, L"CoordinateSystemBuiltInParameter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pCoordDef, IParameterValueCurveByPoints::Create());
    //设置放置类型
    const IFamilyParameterDefinition* pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnLevel));

    //外墙面Id参数
    bool bExt = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(ExteriorFaceNodeTag), PARAMETER_UID(ExteriorFaceNodeTagBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    //内墙面Id参数
    bool bInt = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(InteriorFaceNodeTag), PARAMETER_UID(InteriorFaceNodeTagBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);

    //墙的厚度参数
    double wallThickness = 200;
    bool bT = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(wallThickness), PARAMETER_UID(CoreThicknessBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    //墙的结构类型
    int nType = 2;
    bool bType = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(nType), PARAMETER_UID(WallStructureTypeBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS((bExt && bInt && bT && bType), L"创建墙模板参数有问题",L"GDMPLab",L"2024-03-30");
    //墙的长度，线式族默认的参考线为从坐标系原点沿着X轴正方向，长度为“线式族长度”族参数标注的长度
    double dLength = 4000;

    //墙的高度参数
    double wallHeight = 3000;
    if (isVariableSectionWall)
    {
        bool isOk = AddVariableSectionWallParameters(pDbDoc, pFamilyManager);
        DBG_WARN_AND_RETURN_VOID_UNLESS(isOk, L"变截面墙高度参数添加失败",L"GDMPLab",L"2024-03-30");
        // 墙类型参数
        isOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create((int)StructureWallType::VariableSection), PARAMETER_UID(CategorySubTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
        DBG_WARN_AND_RETURN_VOID_UNLESS(isOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");
    }
    else
    {
        //TODO： 这里的IParameterValidator::CreateRangeValidatorForDouble是为了测试参数验证器而添加，如有不合适请删除
        OwnerPtr<IParameterValueDouble> opParamValueDouble = IParameterValueDouble::Create(wallHeight);
        opParamValueDouble->SetValidator(IParameterValidator::CreateDoubleRangeValidator(0, 1000000));
        bool isOk = AddBuiltInParameterDefination(pDbDoc, TransferOwnership(opParamValueDouble), PARAMETER_UID(WallHeightBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
        DBG_WARN_AND_RETURN_VOID_UNLESS(isOk, L"墙高度参数添加失败",L"GDMPLab",L"2024-03-30");
        // 墙类型参数
        isOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create((int)StructureWallType::Basic), PARAMETER_UID(CategorySubTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
        DBG_WARN_AND_RETURN_VOID_UNLESS(isOk, L"创建类型参数失败",L"GDMPLab",L"2024-03-30");
    }

    //创建参照平面
    {
        DefaultReferencePlanes refPlanes;
        ReferencePlaneOffsets refPlaneOffsets(0, dLength, wallThickness*0.5, wallThickness*0.5, wallHeight, 0);
        DefaultReferencePlanesOptions refPlaneOptions = (DefaultReferencePlanesOptions)(RightReferencePlane | TopReferencePlane | FrontReferencePlane | BackReferencePlane);
        bool result = CreateDefaultReferencePlanes(pDbDoc, refPlaneOptions, refPlaneOffsets, refPlanes);
        DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        refPlaneOptions = (DefaultReferencePlanesOptions)(LeftRightCenterReferencePlane | FrontBackCenterReferencePlane | TopBottomCenterReferencePlane);
        result = GetDefaultReferencePlanes(pDbDoc, refPlaneOptions, refPlanes);
        DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"获取参照平面失败",L"GDMPLab",L"2024-03-30");

        Coordinate3d coordXOY(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
        Coordinate3d coordYOZ(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);
        Coordinate3d coordXOZ(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitZ);

        // 厚度
        DBG_WARN_AND_RETURN_VOID_UNLESS(refPlanes.m_pFrontBackCenter && refPlanes.m_pFront && refPlanes.m_pBack, L"厚度相关参照平面为空",L"GDMPLab",L"2024-03-30");
        {
            // 创建厚度距离约束
            Vector3d dimPosition(-FamilyTemplateConst::CommonExtend, 0, 0);
            gfam::IFamilyDistanceConstraint* pDistanceConstraintWidth = CreateDistanceConstraint(pDbDoc, refPlanes.m_pBack, refPlanes.m_pFront, coordXOY, dimPosition);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pDistanceConstraintWidth, L"pDistanceConstraintWidth为空",L"GDMPLab",L"2024-03-30");

            // 厚度距离约束绑定到厚度参数
            const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(CoreThicknessBuiltInParameter));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
            pDistanceConstraintWidth->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());

            // 墙两侧距离X坐标轴等距
            Vector3d dimPositionEqual(dLength + FamilyTemplateConst::CommonExtend, 0, 0);
            IFamilyDistanceRatioConstraint* pEqualConstraint = CreateEqualConstraint(pDbDoc, refPlanes.m_pFront, refPlanes.m_pBack, refPlanes.m_pFrontBackCenter
                , coordXOY, dimPositionEqual);
        }

        // 长度
        if (isVariableSectionWall)
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(refPlanes.m_pLeftRightCenter && refPlanes.m_pRight, L"长度相关参照平面为空",L"GDMPLab",L"2024-03-30");
            Vector3d dimPosition(dLength / 2, wallThickness * 0.5 + FamilyTemplateConst::CenterExtend, 0);
            gfam::IFamilyDistanceConstraint* pLengthConstraint = CreateDistanceConstraint(pDbDoc, refPlanes.m_pLeftRightCenter, refPlanes.m_pRight, coordXOY, dimPosition);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pLengthConstraint, L"pLengthConstraint为空",L"GDMPLab",L"2024-03-30");
            const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(LineFamilyLengthBuiltInParameter));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
            pLengthConstraint->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
        }

        // 截面高度
        DBG_WARN_AND_RETURN_VOID_UNLESS(refPlanes.m_pTopBottomCenter && refPlanes.m_pTop, L"高度相关参照平面为空",L"GDMPLab",L"2024-03-30");
        {
            Vector3d dimPosition(0, wallThickness*0.5 + FamilyTemplateConst::CenterExtend, wallHeight*0.5);
            gfam::IFamilyDistanceConstraint* pDistanceConstraintHeight = CreateDistanceConstraint(pDbDoc, refPlanes.m_pTop, refPlanes.m_pTopBottomCenter, coordYOZ, dimPosition);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pDistanceConstraintHeight, L"pDistanceConstraintHeight为空",L"GDMPLab",L"2024-03-30");
            const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(WallHeightBuiltInParameter));
            if (pFamParameterDefinition == nullptr)
            {
                pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(VariableSectionWallMaxHeightBuiltInParameter));
            }
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");

            pDistanceConstraintHeight->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
        }
    }

    // 创建形体及形体上的约束
    CreateSweepBody(pDbDoc, isVariableSectionWall);
}

void gcmp::FamStructureTemplateUtility::InitLineFamilyDocument(gcmp::IDocument* pDbDoc, bool bIsInPlaceEditMode /*= false*/)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");

    //设置族类型的初始坐标数
    IFamilyManager* pFamManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamManager != nullptr, L"pFamManager为空",L"GDMPLab",L"2024-03-30");
    const IFamilyParameterDefinition* pCoordDef = pFamManager->GetFamilyParameterDefinition(PARAMETER_UID(CoordinateSystemBuiltInParameter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCoordDef != nullptr, L"CoordinateSystemBuiltInParameter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamManager->SetParameterValueStorage(pCoordDef, IParameterValueCurveByPoints::Create());

    //设置放置类型
    const IFamilyParameterDefinition* pPosTypeDef = pFamManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnWorkPlane));

    //设置为线式族，需要添加一些初始化的工作
    //线式族默认的参考线为从坐标系原点沿着X轴正方向，长度为“线式族长度”族参数标注的长度
    //没有初始化过线式族
    //添加默认的长度参数、4100任务项 - 参数默认值为2500.0，参照面长度4800，参数不能删除

    double dLength = 2000;
    //double dLength = 10000.0;
    bool bRes = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(dLength), PARAMETER_UID(LineFamilyLengthBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS((bRes), L"创建墙模板参数有问题",L"GDMPLab",L"2024-03-30");

    //如果是在项目文档中创建族，不需要创建参照平面
    if (bIsInPlaceEditMode)
        return;
    {
        //double Ylength = dLength;
        double Ylength = 1800;
        //创建一个参照平面，添加标注
        Vector3d startPtY(dLength, Ylength / 2, 0);
        Vector3d endPtY(dLength, -Ylength / 2, 0);
        gcmp::IReferencePlane* pReferencePlane = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pReferencePlane->GetBasicInformation()->SetName(FAMILY_RIGHT_REFERENCE_PLANE_NAME);
        pReferencePlane->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Right);
        pReferencePlane->SetVisibleUVMin(Vector2d(-Ylength / 2, -Ylength / 2));
        pReferencePlane->SetVisibleUVMax(Vector2d(Ylength / 2, Ylength / 2));

        std::vector<IElement*> allRefPlanes = pDbDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_REFERENCE_PLANE);
        //获得默认的左右中心
        gcmp::IReferencePlane* pReferencePlaneY = nullptr;
        Coordinate3d coordXOY(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
        FOR_EACH(pItem, allRefPlanes)
        {
            IReferencePlane* pRefPlane = quick_cast<IReferencePlane>(pItem);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pRefPlane != nullptr, L"pRefPlane为空",L"GDMPLab",L"2024-03-30");

            if (pRefPlane->GetIsFixed() && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight)
            {
                pReferencePlaneY = pRefPlane;
            }
            if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack)
            {
                pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterExtend, -FamilyTemplateConst::CenterLength / 2));
            }
            if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfTopBottom)
            {
                pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterExtend, -FamilyTemplateConst::CenterLength / 2));
            }
        }
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneY != nullptr, L"默认的Y参照平面为空",L"GDMPLab",L"2024-03-30");

        //创建两个参照平面的距离约束
        if (pReferencePlaneY != nullptr)
        {
            Vector3d dimPosition(dLength / 2, Ylength / 2 - 200, 0);
            gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
            gfam::IFamilyDistanceConstraint* pDistanceConstraint = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOY
                , pReferencePlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
                , pReferencePlaneY->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
            pDistanceConstraint->CalcDimValue();

            gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
            const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(LineFamilyLengthBuiltInParameter));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
            pDistanceConstraint->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
        }
    }
}

void gcmp::FamStructureTemplateUtility::InitWallFamilyDocument2(gcmp::IDocument* pDbDoc, bool bIsInPlaceEditMode /*= false*/, bool isVariableSectionWall /*= false*/)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
    const IFamilyParameterDefinition* pCoordDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(CoordinateSystemBuiltInParameter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCoordDef != nullptr, L"CoordinateSystemBuiltInParameter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pCoordDef, IParameterValueCurveByPoints::Create());
    //设置放置类型
    const IFamilyParameterDefinition* pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnLevel));

    //外墙面Id参数
    int nValue = 0;
    bool bExt = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(nValue), PARAMETER_UID(ExteriorFaceNodeTagBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    //内墙面Id参数
    bool bInt = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(nValue), PARAMETER_UID(InteriorFaceNodeTagBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);

    //墙的厚度参数
    double wallThickness = 200;
    bool bT = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(wallThickness), PARAMETER_UID(WallThicknessBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    //墙的高度参数
    double wallHeight = 3000;
    bool bH = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(wallHeight), PARAMETER_UID(WallHeightBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    //墙的结构类型
    int nType = 0;
    bool bType = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(nType), PARAMETER_UID(WallStructureTypeBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS((bExt && bInt && bT && bH && bType), L"创建墙模板参数有问题",L"GDMPLab",L"2024-03-30");
    //墙的长度
    double dLength = 4000;
    bool bRes = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(dLength), PARAMETER_UID(LineFamilyLengthBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS(bRes, L"创建墙模板参数有问题",L"GDMPLab",L"2024-03-30");
    //线式族默认的参考线为从坐标系原点沿着X轴正方向，长度为“线式族长度”族参数标注的长度

    //墙的高度参数
    double startWallHeight = 2000;
    double endWallHeight = 2500;

    //创建参照平面
    {
        double Rightlength = 750;
        double dBottomLength = 800;
        //创建一个参照平面，添加标注
        Vector3d startPtY(dLength, Rightlength, 0);
        Vector3d endPtY(dLength, -Rightlength, 0);
        gcmp::IReferencePlane* pReferencePlaneRight = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneRight != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pReferencePlaneRight->GetBasicInformation()->SetName(FAMILY_RIGHT_REFERENCE_PLANE_NAME);
        pReferencePlaneRight->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Right);
        pReferencePlaneRight->SetVisibleUVMin(Vector2d(-Rightlength, -FamilyTemplateConst::CommonExtend));
        pReferencePlaneRight->SetVisibleUVMax(Vector2d(Rightlength, FamilyTemplateConst::CommonExtend + wallHeight));

        gcmp::IReferencePlane* pReferencePlaneTop = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(0, -dBottomLength, wallHeight), Vector3d(0, dBottomLength, wallHeight), Vector3d::UnitX);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneTop != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pReferencePlaneTop->GetBasicInformation()->SetName(FAMILY_TOP_REFERENCE_PLANE_NAME);
        pReferencePlaneTop->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Top);
        pReferencePlaneTop->SetVisibleUVMin(Vector2d(-dBottomLength, -FamilyTemplateConst::CommonExtend));
        pReferencePlaneTop->SetVisibleUVMax(Vector2d(dBottomLength, dLength + FamilyTemplateConst::CommonExtend));

        gcmp::IReferencePlane* pReferencePlaneBack = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(-FamilyTemplateConst::CommonExtend, wallThickness * 0.5, 0), Vector3d(FamilyTemplateConst::CommonExtend, wallThickness * 0.5, 0), Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneBack != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pReferencePlaneBack->GetBasicInformation()->SetName(FAMILY_BACK_REFERENCE_PLANE_NAME);
        pReferencePlaneBack->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Back);
        pReferencePlaneBack->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CommonExtend, -FamilyTemplateConst::CommonExtend));
        pReferencePlaneBack->SetVisibleUVMax(Vector2d(dLength + FamilyTemplateConst::CommonExtend, wallHeight + FamilyTemplateConst::CommonExtend));

        gcmp::IReferencePlane* pReferencePlaneFront = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(-FamilyTemplateConst::CommonExtend, -wallThickness * 0.5, 0), Vector3d(FamilyTemplateConst::CommonExtend, -wallThickness * 0.5, 0), Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneFront != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pReferencePlaneFront->GetBasicInformation()->SetName(FAMILY_FRONT_REFERENCE_PLANE_NAME);
        pReferencePlaneFront->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Front);
        pReferencePlaneFront->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CommonExtend, -FamilyTemplateConst::CommonExtend));
        pReferencePlaneFront->SetVisibleUVMax(Vector2d(dLength + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend + wallHeight));

        std::vector<IElement*> allRefPlanes = pDbDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_REFERENCE_PLANE);
        //获得默认的左右中心
        gcmp::IReferencePlane* pReferencePlaneLeftRightCenter = nullptr;
        //获得默认的上下中心
        gcmp::IReferencePlane* pReferencePlaneTopBottomCenter = nullptr;
        //获得默认的前后中心
        gcmp::IReferencePlane* pReferencePlaneFrontBackCenter = nullptr;

        FOR_EACH(pItem, allRefPlanes)
        {
            IReferencePlane* pRefPlane = quick_cast<IReferencePlane>(pItem);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pRefPlane != nullptr, L"pRefPlane为空",L"GDMPLab",L"2024-03-30");

            if (pRefPlane->GetIsFixed() && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight)
            {
                pReferencePlaneLeftRightCenter = pRefPlane;
                pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterLength * 0.5, -FamilyTemplateConst::CenterExtend));
                pRefPlane->SetVisibleUVMax(Vector2d(FamilyTemplateConst::CenterLength * 0.5, FamilyTemplateConst::CenterExtend + wallHeight));
            }
            if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack)
            {
                pReferencePlaneFrontBackCenter = pRefPlane;
                pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterExtend, -FamilyTemplateConst::CenterExtend));
                pRefPlane->SetVisibleUVMax(Vector2d(dLength + FamilyTemplateConst::CenterExtend, FamilyTemplateConst::CenterExtend + wallHeight));
            }
            if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfTopBottom)
            {
                pReferencePlaneTopBottomCenter = pRefPlane;
                pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterExtend, -FamilyTemplateConst::CenterLength * 0.5));
                pRefPlane->SetVisibleUVMax(Vector2d(dLength + FamilyTemplateConst::CenterExtend, FamilyTemplateConst::CenterLength * 0.5));
            }
        }
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneLeftRightCenter != nullptr, L"默认的Y参照平面为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneFrontBackCenter != nullptr, L"默认的X参照平面为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneTopBottomCenter != nullptr, L"默认的Z参照平面为空",L"GDMPLab",L"2024-03-30");

        Coordinate3d coordXOY(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
        Coordinate3d coordYOZ(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);
        Coordinate3d coordXOZ(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitZ);
        // 创建距离约束
        // 线式族长度约束
        if (pReferencePlaneLeftRightCenter != nullptr)
        {
            Vector3d dimPosition(dLength / 2, wallThickness * 0.5 + FamilyTemplateConst::CenterExtend, 0);
            gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
            gfam::IFamilyDistanceConstraint* pDistanceConstraint = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOY
                , pReferencePlaneRight->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
                , pReferencePlaneLeftRightCenter->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
            pDistanceConstraint->CalcDimValue();

            gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
            const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(LineFamilyLengthBuiltInParameter));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
            pDistanceConstraint->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
        }

        // 厚度
        if (pReferencePlaneFrontBackCenter)
        {
            Vector3d dimPosition(-FamilyTemplateConst::CommonExtend, 0, 0);
            gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
            gfam::IFamilyDistanceConstraint* pDistanceConstraintWidth = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOY
                , pReferencePlaneBack->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
                , pReferencePlaneFront->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
            pDistanceConstraintWidth->CalcDimValue();

            gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
            const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(WallThicknessBuiltInParameter));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
            pDistanceConstraintWidth->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());

            Vector3d dimPositionEqual(dLength + FamilyTemplateConst::CommonExtend, 0, 0);
            IFamilyMultiDistanceDimension* pDimEqual = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPositionEqual, FamilyTemplateConst::DimScale, ElementId(), ElementId(), coordXOY, true);
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pReferencePlaneFront->GetElementId(), GraphicsNodeId(1));
            pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
            pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pReferencePlaneBack->GetElementId(), GraphicsNodeId(1));
            pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

            IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDbDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), coordYOZ);
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pReferencePlaneFront->GetElementId(), GraphicsNodeId(1));
            pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
            pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pReferencePlaneBack->GetElementId(), GraphicsNodeId(1));
            pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
            pEqualConstraint->SetRatioValue(0.5);

            pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
        }

        // 截面高度
        if (pReferencePlaneTopBottomCenter)
        {
            Vector3d dimPosition(0, wallThickness * 0.5 + FamilyTemplateConst::CenterExtend, wallHeight * 0.5);
            gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
            gfam::IFamilyDistanceConstraint* pDistanceConstraintHeight = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordYOZ
                , pReferencePlaneTop->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
                , pReferencePlaneTopBottomCenter->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
            pDistanceConstraintHeight->CalcDimValue();

            gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
            const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(WallHeightBuiltInParameter));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
            pDistanceConstraintHeight->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
        }

        //变截面墙
        if (isVariableSectionWall)
        {
            //创建参照线
            startPtY = Vector3d(0, 0, startWallHeight);
            endPtY = Vector3d(dLength, 0, endWallHeight);
            IFamilyReferenceLine* pRefLine = IFamilyReferenceLine::CreateAsStraightLine(pDbDoc, pReferencePlaneFrontBackCenter->GetElementId(), startPtY, endPtY);

            //参照线的起点和上下中心的距离约束
            Vector3d dimPosition(-FamilyTemplateConst::CenterExtend, 0, startWallHeight / 2);
            gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
            gfam::IFamilyDistanceConstraint* pDistanceConstraint1 = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOZ
                , pRefLine->GetOwnerElementId(), gcmp::GraphicsNodeReferenceType::StartPoint, gcmp::GraphicsNodeId(1)
                , pReferencePlaneTopBottomCenter->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
            pDistanceConstraint1->CalcDimValue();

            //参照线的起点在左右中心参照平面上
            CreateEqualConstraint(pDbDoc, coordXOZ, pReferencePlaneLeftRightCenter, gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, GraphicsNodeId(1), pRefLine->GetOwnerElement(), gcmp::GraphicsNodeReferenceType::StartPoint, GraphicsNodeId(1));

            //参照线的终点和上下中心的距离约束
            dimPosition = Vector3d(dLength + FamilyTemplateConst::CenterExtend, 0, startWallHeight / 2);
            gfam::IFamilyDistanceConstraint* pDistanceConstraint2 = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOZ
                , pRefLine->GetOwnerElementId(), gcmp::GraphicsNodeReferenceType::EndPoint, gcmp::GraphicsNodeId(1)
                , pReferencePlaneTopBottomCenter->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
            pDistanceConstraint2->CalcDimValue();

            //参照线的终点在右参照平面上
            CreateEqualConstraint(pDbDoc, coordXOZ, pReferencePlaneRight, gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, GraphicsNodeId(1), pRefLine->GetOwnerElement(), gcmp::GraphicsNodeReferenceType::EndPoint, GraphicsNodeId(1));
        }

    }

    // 创建形体及形体上的约束
    CreateBuiltInWallBody(pDbDoc, PARAMETER_UID(WallThicknessBuiltInParameter), isVariableSectionWall);
}

void gcmp::FamStructureTemplateUtility::InitWindowFamilyDocument(gcmp::IDocument* pDbDoc, bool bIsInPlaceEditMode /*= false*/)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    //设置放置类型为基于Host的点式族(门，窗有host)
    const IFamilyParameterDefinition* pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnHost));

    //添加墙的厚度参数、参数默认值为200，参数不能删除，用于洞口的扣减体根据墙的厚度更新
    double wallThickness = 200;
    //添加默认的窗台高度参数、参数默认值为800，参数不能删除
    double windowSillHeight = 800;
    //添加窗的高度参数、参数默认值为1500，参数不能删除
    double windowHeight = 1500;
    //添加窗的宽度参数、参数默认值为1000，参数不能删除
    double windowWidth = 1000;
    AddWindowParameterDefination(pDbDoc, wallThickness, windowSillHeight, windowHeight, windowWidth);

    //如果是在项目文档中创建族，不需要创建参照平面
    if (bIsInPlaceEditMode)
        return;

    //创建的参照平面的默认长度
    Coordinate3d coordXOY(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    Coordinate3d coordXOZ(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitZ);
    IReferencePlane* pLeftReferencePlane = nullptr;
    IReferencePlane* pRightReferencePlane = nullptr;
    IReferencePlane* pExteriorReferencePlane = nullptr;
    IReferencePlane* pInteriorReferencePlane = nullptr;
    IReferencePlane* pTopReferencePlane = nullptr;

    {
        //创建左侧参照平面
        Vector3d startPtY(-windowWidth * 0.5, -windowWidth * 0.5, 0);
        Vector3d endPtY(-windowWidth * 0.5, windowWidth * 0.5, 0);
        pLeftReferencePlane = ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pLeftReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pLeftReferencePlane->GetBasicInformation()->SetName(FAMILY_LEFT_REFERENCE_PLANE_NAME);
        pLeftReferencePlane->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Left);
        pLeftReferencePlane->SetVisibleUVMin(Vector2d(-wallThickness * 0.5 - FamilyTemplateConst::CommonExtend, -FamilyTemplateConst::CommonExtend));
        pLeftReferencePlane->SetVisibleUVMax(Vector2d(wallThickness * 0.5 + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend + windowHeight));
    }

    {
        //创建右侧参照平面
        Vector3d startPtY(windowWidth * 0.5, -windowWidth * 0.5, 0);
        Vector3d endPtY(windowWidth * 0.5, windowWidth * 0.5, 0);
        pRightReferencePlane = ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pRightReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pRightReferencePlane->GetBasicInformation()->SetName(FAMILY_RIGHT_REFERENCE_PLANE_NAME);
        pRightReferencePlane->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Right);
        pRightReferencePlane->SetVisibleUVMin(Vector2d(-wallThickness * 0.5 - FamilyTemplateConst::CommonExtend, -FamilyTemplateConst::CommonExtend));
        pRightReferencePlane->SetVisibleUVMax(Vector2d(wallThickness * 0.5 + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend + windowHeight));
    }

    {
        //创建外部参照平面
        Vector3d startPtY(-windowWidth * 0.5 - FamilyTemplateConst::CommonExtend, wallThickness * 0.5, 0);
        Vector3d endPtY(windowWidth * 0.5 + FamilyTemplateConst::CommonExtend, wallThickness * 0.5, 0);
        pExteriorReferencePlane = ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pExteriorReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pExteriorReferencePlane->GetBasicInformation()->SetName(FAMILY_OUTER_REFERENCE_PLANE_NAME);
        pExteriorReferencePlane->SetVisibleUVMin(Vector2d(-windowWidth * 0.5 - FamilyTemplateConst::CommonExtend, -FamilyTemplateConst::CommonExtend));
        pExteriorReferencePlane->SetVisibleUVMax(Vector2d(windowWidth * 0.5 + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend + windowHeight));
    }

    {
        //创建内部参照平面
        Vector3d startPtY(-windowWidth * 0.5 - FamilyTemplateConst::CommonExtend, -wallThickness * 0.5, 0);
        Vector3d endPtY(windowWidth * 0.5 + FamilyTemplateConst::CommonExtend, -wallThickness * 0.5, 0);
        pInteriorReferencePlane = ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pInteriorReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pInteriorReferencePlane->GetBasicInformation()->SetName(FAMILY_INNER_REFERENCE_PLANE_NAME);
        pInteriorReferencePlane->SetVisibleUVMin(Vector2d(-windowWidth * 0.5 - FamilyTemplateConst::CommonExtend, -FamilyTemplateConst::CommonExtend));
        pInteriorReferencePlane->SetVisibleUVMax(Vector2d(windowWidth * 0.5 + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend + windowHeight));
    }

    {
        //创建门的高度对应的参照平面
        Vector3d startPtY(-FamilyTemplateConst::CenterLength * 0.5, 0, windowHeight);
        Vector3d endPtY(FamilyTemplateConst::CenterLength * 0.5, 0, windowHeight);
        pTopReferencePlane = ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitY);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pTopReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pTopReferencePlane->GetBasicInformation()->SetName(FAMILY_TOP_REFERENCE_PLANE_NAME);
        pTopReferencePlane->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Top);
    }

    //获得默认的参照平面
    std::vector<IElement*> allRefPlanes = pDbDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_REFERENCE_PLANE);
    //获得默认的左右中心
    gcmp::IReferencePlane* pReferencePlaneLeftRightCenter = nullptr;
    gcmp::IReferencePlane* pReferencePlaneFrontBackCenter = nullptr;

    FOR_EACH(pItem, allRefPlanes)
    {
        IReferencePlane* pRefPlane = quick_cast<IReferencePlane>(pItem);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pRefPlane != nullptr, L"pRefPlane为空",L"GDMPLab",L"2024-03-30");

        if (pRefPlane->GetIsFixed() && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight)
        {
            pReferencePlaneLeftRightCenter = pRefPlane;
            pRefPlane->SetVisibleUVMin(Vector2d(-wallThickness * 0.5 - FamilyTemplateConst::CenterExtend, -FamilyTemplateConst::CenterExtend));
            pRefPlane->SetVisibleUVMax(Vector2d(wallThickness * 0.5 + FamilyTemplateConst::CenterExtend, windowHeight + FamilyTemplateConst::CenterExtend));
        }
        if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack)
        {
            pReferencePlaneFrontBackCenter = pRefPlane;
            pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterExtend - windowWidth * 0.5, -FamilyTemplateConst::CenterExtend));
            pRefPlane->SetVisibleUVMax(Vector2d(windowWidth * 0.5 + FamilyTemplateConst::CenterExtend, FamilyTemplateConst::CenterExtend + windowHeight));
        }
    }
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneFrontBackCenter != nullptr, L"默认的X参照平面为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneLeftRightCenter != nullptr, L"默认的Y参照平面为空",L"GDMPLab",L"2024-03-30");

    IReferencePlane* pReferencePlaneZ = nullptr;
    std::vector<IReferencePlane*> resultReferencePlanesInXOZ;
    ReferencePlaneUtils::GetVisibleReferencePlanes(pDbDoc, coordXOZ, resultReferencePlanesInXOZ);
    for (auto iter = resultReferencePlanesInXOZ.begin(); iter != resultReferencePlanesInXOZ.end(); ++iter)
    {
        if ((*iter)->GetIsFixed() && (*iter)->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfTopBottom)
        {
            pReferencePlaneZ = *iter;
            continue;
        }
    }

    {
        //创建左右两个参照平面的距离约束
        Vector3d dimPosition(0, 0, -FamilyTemplateConst::CommonExtend);
        IFamilyMultiDistanceDimension* pDim = nullptr;
        IFamilyDistanceConstraint* pDistanceConstraint = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOZ
            , pLeftReferencePlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
            , pRightReferencePlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
        pDistanceConstraint->CalcDimValue();

        const gfam::IFamilyParameterDefinition* pDoorWidthParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(DoorOrWindowWidthBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDoorWidthParameter != nullptr, L"pDoorWidthParameter为空",L"GDMPLab",L"2024-03-30");
        pDistanceConstraint->SetFamilyParameterDefinitionId(pDoorWidthParameter->GetElementId());

        //创建相等约束
        Vector3d dimPositionEqual(0, 0, windowHeight + FamilyTemplateConst::CommonExtend);
        IFamilyMultiDistanceDimension* pDimEqual = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPositionEqual, FamilyTemplateConst::DimScale, ElementId(), ElementId(), coordXOZ, true);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pLeftReferencePlane->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pReferencePlaneLeftRightCenter->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pRightReferencePlane->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

        IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDbDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), coordXOZ);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pLeftReferencePlane->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pReferencePlaneLeftRightCenter->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pRightReferencePlane->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
        pEqualConstraint->SetRatioValue(0.5);

        pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
    }

    {
        //创建内部和外部两个参照平面的距离约束
        Vector3d dimPosition(-windowWidth * 0.5 - FamilyTemplateConst::CommonExtend, 0, 0);
        IFamilyMultiDistanceDimension* pDim = nullptr;
        IFamilyDistanceConstraint* pDistanceConstraint = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOY
            , pExteriorReferencePlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
            , pInteriorReferencePlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
        pDistanceConstraint->CalcDimValue();

        const gfam::IFamilyParameterDefinition* pWallThicknessParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(WallThicknessBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pWallThicknessParameter != nullptr, L"pWallThicknessParameter为空",L"GDMPLab",L"2024-03-30");
        pDistanceConstraint->SetFamilyParameterDefinitionId(pWallThicknessParameter->GetElementId());

        //创建相等约束
        Vector3d dimPositionEqual(windowWidth * 0.5 + FamilyTemplateConst::CommonExtend, 0, 0);
        IFamilyMultiDistanceDimension* pDimEqual = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPositionEqual, FamilyTemplateConst::DimScale, ElementId(), ElementId(), coordXOY, true);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pExteriorReferencePlane->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pInteriorReferencePlane->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

        IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDbDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), coordXOY);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pExteriorReferencePlane->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pInteriorReferencePlane->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
        pEqualConstraint->SetRatioValue(0.5);

        pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
    }

    {
        //创建门的高度对应的距离约束
        Vector3d dimPosition(-windowWidth * 0.5 - 700, 0, windowHeight * 0.5);
        IFamilyMultiDistanceDimension* pDim = nullptr;
        IFamilyDistanceConstraint* pDistanceConstraint = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOZ
            , pTopReferencePlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
            , pReferencePlaneZ->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
        pDistanceConstraint->CalcDimValue();

        const gfam::IFamilyParameterDefinition* pDoorHeightParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(DoorOrWindowHeightBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDoorHeightParameter != nullptr, L"pDoorHeightParameter为空",L"GDMPLab",L"2024-03-30");
        pDistanceConstraint->SetFamilyParameterDefinitionId(pDoorHeightParameter->GetElementId());
    }
}

void gcmp::FamStructureTemplateUtility::InitDoorFamilyDocument(gcmp::IDocument* pDbDoc, bool bIsInPlaceEditMode /*= false*/)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    //设置放置类型为基于Host的点式族(门，窗有host)
    const IFamilyParameterDefinition* pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnHost));

    //添加墙的厚度参数、参数默认值为300，参数不能删除，用于洞口的扣减体根据墙的厚度更新
    double wallThickness = 200;
    //添加门的高度参数、参数默认值为2000，参数不能删除
    double doorHeight = 2000;
    //添加门的宽度参数、参数默认值为1000，参数不能删除
    double doorWidth = 1000;
    AddDoorParameterDefination(pDbDoc, wallThickness, doorHeight, doorWidth);

    //如果是在项目文档中创建族，不需要创建参照平面
    if (bIsInPlaceEditMode)
        return;

    //创建的参照平面的默认长度
    Coordinate3d coordXOY(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    Coordinate3d coordXOZ(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitZ);
    IReferencePlane* pLeftReferencePlane = nullptr;
    IReferencePlane* pRightReferencePlane = nullptr;
    IReferencePlane* pExteriorReferencePlane = nullptr;
    IReferencePlane* pInteriorReferencePlane = nullptr;
    IReferencePlane* pTopReferencePlane = nullptr;

    {
        //创建左侧参照平面
        Vector3d startPtY(-doorWidth * 0.5, -doorWidth * 0.5, 0);
        Vector3d endPtY(-doorWidth * 0.5, doorWidth * 0.5, 0);
        pLeftReferencePlane = ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pLeftReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pLeftReferencePlane->GetBasicInformation()->SetName(FAMILY_LEFT_REFERENCE_PLANE_NAME);
        pLeftReferencePlane->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Left);
        pLeftReferencePlane->SetVisibleUVMin(Vector2d(-wallThickness * 0.5 - FamilyTemplateConst::CommonExtend, -FamilyTemplateConst::CommonExtend));
        pLeftReferencePlane->SetVisibleUVMax(Vector2d(wallThickness * 0.5 + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend + doorHeight));
    }

    {
        //创建右侧参照平面
        Vector3d startPtY(doorWidth * 0.5, -doorWidth * 0.5, 0);
        Vector3d endPtY(doorWidth * 0.5, doorWidth * 0.5, 0);
        pRightReferencePlane = ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pRightReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pRightReferencePlane->GetBasicInformation()->SetName(FAMILY_RIGHT_REFERENCE_PLANE_NAME);
        pRightReferencePlane->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Right);
        pRightReferencePlane->SetVisibleUVMin(Vector2d(-wallThickness * 0.5 - FamilyTemplateConst::CommonExtend, -FamilyTemplateConst::CommonExtend));
        pRightReferencePlane->SetVisibleUVMax(Vector2d(wallThickness * 0.5 + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend + doorHeight));
    }

    {
        //创建外部参照平面
        Vector3d startPtY(-doorWidth * 0.5 - FamilyTemplateConst::CommonExtend, wallThickness * 0.5, 0);
        Vector3d endPtY(doorWidth * 0.5 + FamilyTemplateConst::CommonExtend, wallThickness * 0.5, 0);
        pExteriorReferencePlane = ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pExteriorReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pExteriorReferencePlane->GetBasicInformation()->SetName(FAMILY_OUTER_REFERENCE_PLANE_NAME);
        pExteriorReferencePlane->SetVisibleUVMin(Vector2d(-doorWidth * 0.5 - FamilyTemplateConst::CommonExtend, -FamilyTemplateConst::CommonExtend));
        pExteriorReferencePlane->SetVisibleUVMax(Vector2d(doorWidth * 0.5 + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend + doorHeight));
    }

    {
        //创建内部参照平面
        Vector3d startPtY(-doorWidth * 0.5 - FamilyTemplateConst::CommonExtend, -wallThickness * 0.5, 0);
        Vector3d endPtY(doorWidth * 0.5 + FamilyTemplateConst::CommonExtend, -wallThickness * 0.5, 0);
        pInteriorReferencePlane = ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pInteriorReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pInteriorReferencePlane->GetBasicInformation()->SetName(FAMILY_INNER_REFERENCE_PLANE_NAME);
        pInteriorReferencePlane->SetVisibleUVMin(Vector2d(-doorWidth * 0.5 - FamilyTemplateConst::CommonExtend, -FamilyTemplateConst::CommonExtend));
        pInteriorReferencePlane->SetVisibleUVMax(Vector2d(doorWidth * 0.5 + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend + doorHeight));
    }

    {
        //创建门的高度对应的参照平面
        Vector3d startPtY(-FamilyTemplateConst::CenterLength * 0.5, 0, doorHeight);
        Vector3d endPtY(FamilyTemplateConst::CenterLength * 0.5, 0, doorHeight);
        pTopReferencePlane = ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitY);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pTopReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pTopReferencePlane->GetBasicInformation()->SetName(FAMILY_TOP_REFERENCE_PLANE_NAME);
        pTopReferencePlane->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Top);
    }

    //获得默认的参照平面
    std::vector<IElement*> allRefPlanes = pDbDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_REFERENCE_PLANE);
    //获得默认的左右中心
    gcmp::IReferencePlane* pReferencePlaneLeftRightCenter = nullptr;
    gcmp::IReferencePlane* pReferencePlaneFrontBackCenter = nullptr;

    FOR_EACH(pItem, allRefPlanes)
    {
        IReferencePlane* pRefPlane = quick_cast<IReferencePlane>(pItem);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pRefPlane != nullptr, L"pRefPlane为空",L"GDMPLab",L"2024-03-30");

        if (pRefPlane->GetIsFixed() && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight)
        {
            pReferencePlaneLeftRightCenter = pRefPlane;
            pRefPlane->SetVisibleUVMin(Vector2d(-wallThickness * 0.5 - FamilyTemplateConst::CenterExtend, -FamilyTemplateConst::CenterExtend));
            pRefPlane->SetVisibleUVMax(Vector2d(wallThickness * 0.5 + FamilyTemplateConst::CenterExtend, doorHeight + FamilyTemplateConst::CenterExtend));
        }
        if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack)
        {
            pReferencePlaneFrontBackCenter = pRefPlane;
            pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterExtend - doorWidth * 0.5, -FamilyTemplateConst::CenterExtend));
            pRefPlane->SetVisibleUVMax(Vector2d(doorWidth * 0.5 + FamilyTemplateConst::CenterExtend, FamilyTemplateConst::CenterExtend + doorHeight));
        }
    }
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneFrontBackCenter != nullptr, L"默认的X参照平面为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneLeftRightCenter != nullptr, L"默认的Y参照平面为空",L"GDMPLab",L"2024-03-30");

    IReferencePlane* pReferencePlaneZ = nullptr;
    std::vector<IReferencePlane*> resultReferencePlanesInXOZ;
    ReferencePlaneUtils::GetVisibleReferencePlanes(pDbDoc, coordXOZ, resultReferencePlanesInXOZ);
    for (auto iter = resultReferencePlanesInXOZ.begin(); iter != resultReferencePlanesInXOZ.end(); ++iter)
    {
        if ((*iter)->GetIsFixed() && (*iter)->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfTopBottom)
        {
            pReferencePlaneZ = *iter;
            continue;
        }
    }

    {
        //创建左右两个参照平面的距离约束
        Vector3d dimPosition(0, 0, -FamilyTemplateConst::CommonExtend);
        IFamilyMultiDistanceDimension* pDim = nullptr;
        IFamilyDistanceConstraint* pDistanceConstraint = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOZ
            , pLeftReferencePlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
            , pRightReferencePlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
        pDistanceConstraint->CalcDimValue();

        const gfam::IFamilyParameterDefinition* pDoorWidthParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(DoorOrWindowWidthBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDoorWidthParameter != nullptr, L"pDoorWidthParameter为空",L"GDMPLab",L"2024-03-30");
        pDistanceConstraint->SetFamilyParameterDefinitionId(pDoorWidthParameter->GetElementId());

        //创建相等约束
        Vector3d dimPositionEqual(0, 0, doorHeight + FamilyTemplateConst::CommonExtend);
        IFamilyMultiDistanceDimension* pDimEqual = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPositionEqual, FamilyTemplateConst::DimScale, ElementId(), ElementId(), coordXOZ, true);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pLeftReferencePlane->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pReferencePlaneLeftRightCenter->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pRightReferencePlane->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

        IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDbDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), coordXOZ);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pLeftReferencePlane->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pReferencePlaneLeftRightCenter->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pRightReferencePlane->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
        pEqualConstraint->SetRatioValue(0.5);

        pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
    }

    {
        //创建内部和外部两个参照平面的距离约束
        Vector3d dimPosition(-doorWidth * 0.5 - FamilyTemplateConst::CommonExtend, 0, 0);
        IFamilyMultiDistanceDimension* pDim = nullptr;
        IFamilyDistanceConstraint* pDistanceConstraint = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOY
            , pExteriorReferencePlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
            , pInteriorReferencePlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
        pDistanceConstraint->CalcDimValue();

        const gfam::IFamilyParameterDefinition* pWallThicknessParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(WallThicknessBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pWallThicknessParameter != nullptr, L"pWallThicknessParameter为空",L"GDMPLab",L"2024-03-30");
        pDistanceConstraint->SetFamilyParameterDefinitionId(pWallThicknessParameter->GetElementId());

        //创建相等约束
        Vector3d dimPositionEqual(doorWidth * 0.5 + FamilyTemplateConst::CommonExtend, 0, 0);
        IFamilyMultiDistanceDimension* pDimEqual = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPositionEqual, FamilyTemplateConst::DimScale, ElementId(), ElementId(), coordXOY, true);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pExteriorReferencePlane->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pInteriorReferencePlane->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

        IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDbDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), coordXOY);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pExteriorReferencePlane->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pInteriorReferencePlane->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
        pEqualConstraint->SetRatioValue(0.5);

        pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
    }

    {
        //创建门的高度对应的距离约束
        Vector3d dimPosition(-doorWidth * 0.5 - 700, 0, doorHeight * 0.5);
        IFamilyMultiDistanceDimension* pDim = nullptr;
        IFamilyDistanceConstraint* pDistanceConstraint = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOZ
            , pTopReferencePlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
            , pReferencePlaneZ->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
        pDistanceConstraint->CalcDimValue();

        const gfam::IFamilyParameterDefinition* pDoorHeightParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(DoorOrWindowHeightBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDoorHeightParameter != nullptr, L"pDoorHeightParameter为空",L"GDMPLab",L"2024-03-30");
        pDistanceConstraint->SetFamilyParameterDefinitionId(pDoorHeightParameter->GetElementId());
    }
}

void gcmp::FamStructureTemplateUtility::InitBeamFamilyDocument(gcmp::IDocument* pDbDoc, bool bIsInPlaceEditMode /*= false*/)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
    const IFamilyParameterDefinition* pCoordDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(CoordinateSystemBuiltInParameter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCoordDef != nullptr, L"CoordinateSystemBuiltInParameter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pCoordDef, IParameterValueCurveByPoints::Create());
    //设置放置类型
    const IFamilyParameterDefinition* pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnLevel));

    //外面Id参数
    int nValue = 0;
    bool bExt = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(nValue), PARAMETER_UID(ExteriorFaceNodeTagBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    //内面Id参数
    bool bInt = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(nValue), PARAMETER_UID(InteriorFaceNodeTagBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);

    //梁的结构类型
    int nStructureType = 0;
    bool bSType = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(nStructureType), PARAMETER_UID(BeamStructureTypeBuiltInParameter), true, false, L"", ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS(bSType, L"创建梁模板参数有问题",L"GDMPLab",L"2024-03-30");
    SetFamParameterType(pDbDoc, PARAMETER_UID(BeamStructureTypeBuiltInParameter), FamilyParameterType::Integer);

    //梁的截面宽度
    double secWidth = 600;
    bool bRes = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(secWidth), PARAMETER_UID(RectSectionWidthBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS(bRes, L"创建梁模板参数有问题",L"GDMPLab",L"2024-03-30");
    //梁的截面高度
    double secHeight = 1000;
    bRes = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(secHeight), PARAMETER_UID(RectSectionHeightBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS(bRes, L"创建梁模板参数有问题",L"GDMPLab",L"2024-03-30");
    //梁的截面的旋转角度
    double secRotAngle = 0;
    bRes = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(secRotAngle), PARAMETER_UID(SectionRotateAngleBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS(bRes, L"创建梁模板参数有问题",L"GDMPLab",L"2024-03-30");
    SetFamParameterType(pDbDoc, PARAMETER_UID(SectionRotateAngleBuiltInParameter), FamilyParameterType::Angle);

    //增加截面类型
    gcmp::EnSectionShapeType sectType = gcmp::SECTION_SHAPE_RECTANGLE;
    bRes = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create((int)sectType), PARAMETER_UID(SectionTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS(bRes, L"创建梁模板参数有问题",L"GDMPLab",L"2024-03-30");
    SetFamParameterType(pDbDoc, PARAMETER_UID(SectionTypeBuiltInParameter), FamilyParameterType::Integer);

    double dLength = 4000;
    bRes = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(dLength), PARAMETER_UID(LineFamilyLengthBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS(bRes, L"创建墙模板参数有问题",L"GDMPLab",L"2024-03-30");
    //线式族默认的参考线为从坐标系原点沿着X轴正方向，长度为“线式族长度”族参数标注的长度
    {
        double Rightlength = 750;
        double dBottomLength = 800;
        //创建一个参照平面，添加标注
        Vector3d startPtY(dLength, Rightlength, 0);
        Vector3d endPtY(dLength, -Rightlength, 0);
        gcmp::IReferencePlane* pReferencePlaneRight = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneRight != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pReferencePlaneRight->GetBasicInformation()->SetName(FAMILY_RIGHT_REFERENCE_PLANE_NAME);
        pReferencePlaneRight->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Right);
        pReferencePlaneRight->SetVisibleUVMin(Vector2d(-Rightlength, -secHeight - FamilyTemplateConst::CommonExtend));
        pReferencePlaneRight->SetVisibleUVMax(Vector2d(Rightlength, FamilyTemplateConst::CommonExtend));

        gcmp::IReferencePlane* pReferencePlaneBottom = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(0, -dBottomLength, -secHeight), Vector3d(0, dBottomLength, -secHeight), Vector3d::UnitX);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneBottom != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pReferencePlaneBottom->GetBasicInformation()->SetName(FAMILY_BOTTOM_REFERENCE_PLANE_NAME);
        pReferencePlaneBottom->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Bottom);
        pReferencePlaneBottom->SetVisibleUVMin(Vector2d(-dBottomLength, -FamilyTemplateConst::CommonExtend));
        pReferencePlaneBottom->SetVisibleUVMax(Vector2d(dBottomLength, dLength + FamilyTemplateConst::CommonExtend));

        gcmp::IReferencePlane* pReferencePlaneBack = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(-FamilyTemplateConst::CommonExtend, secWidth * 0.5, 0), Vector3d(FamilyTemplateConst::CommonExtend, secWidth * 0.5, 0), Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneBack != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pReferencePlaneBack->GetBasicInformation()->SetName(FAMILY_BACK_REFERENCE_PLANE_NAME);
        pReferencePlaneBack->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Back);
        pReferencePlaneBack->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CommonExtend, -secHeight - FamilyTemplateConst::CommonExtend));
        pReferencePlaneBack->SetVisibleUVMax(Vector2d(dLength + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend));

        gcmp::IReferencePlane* pReferencePlaneFront = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(-FamilyTemplateConst::CommonExtend, -secWidth * 0.5, 0), Vector3d(FamilyTemplateConst::CommonExtend, -secWidth * 0.5, 0), Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneFront != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pReferencePlaneFront->GetBasicInformation()->SetName(FAMILY_FRONT_REFERENCE_PLANE_NAME);
        pReferencePlaneFront->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Front);
        pReferencePlaneFront->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CommonExtend, -secHeight - FamilyTemplateConst::CommonExtend));
        pReferencePlaneFront->SetVisibleUVMax(Vector2d(dLength + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend));

        std::vector<IElement*> allRefPlanes = pDbDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_REFERENCE_PLANE);
        //获得默认的左右中心
        gcmp::IReferencePlane* pReferencePlaneLeftRightCenter = nullptr;
        gcmp::IReferencePlane* pReferencePlaneTopBottomCenter = nullptr;
        gcmp::IReferencePlane* pReferencePlaneFrontBackCenter = nullptr;

        FOR_EACH(pItem, allRefPlanes)
        {
            IReferencePlane* pRefPlane = quick_cast<IReferencePlane>(pItem);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pRefPlane != nullptr, L"pRefPlane为空",L"GDMPLab",L"2024-03-30");

            if (pRefPlane->GetIsFixed() && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight)
            {
                pReferencePlaneLeftRightCenter = pRefPlane;
            }
            if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack)
            {
                pReferencePlaneFrontBackCenter = pRefPlane;
                pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterExtend, -secHeight - FamilyTemplateConst::CenterExtend));
                pRefPlane->SetVisibleUVMax(Vector2d(dLength + FamilyTemplateConst::CenterExtend, FamilyTemplateConst::CenterExtend));
            }
            if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfTopBottom)
            {
                pReferencePlaneTopBottomCenter = pRefPlane;
                pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterExtend, -FamilyTemplateConst::CenterLength * 0.5));
                pRefPlane->SetVisibleUVMax(Vector2d(dLength + FamilyTemplateConst::CenterExtend, FamilyTemplateConst::CenterLength * 0.5));
            }
        }
        DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneLeftRightCenter != nullptr, L"默认的Y参照平面为空",L"GDMPLab",L"2024-03-30");

        Coordinate3d coordXOY(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
        Coordinate3d coordYOZ(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);
        // 创建距离约束
        // 线式族长度约束
        if (pReferencePlaneLeftRightCenter != nullptr)
        {
            Vector3d dimPosition(dLength / 2, secWidth * 0.5 + FamilyTemplateConst::CenterExtend, 0);
            gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
            gfam::IFamilyDistanceConstraint* pDistanceConstraint = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOY
                , pReferencePlaneRight->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
                , pReferencePlaneLeftRightCenter->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
            pDistanceConstraint->CalcDimValue();

            gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
            const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(LineFamilyLengthBuiltInParameter));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
            pDistanceConstraint->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
        }

        // 截面高度
        if (pReferencePlaneTopBottomCenter)
        {
            Vector3d dimPosition(0, secWidth * 0.5 + FamilyTemplateConst::CenterExtend, -secHeight * 0.5);
            gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
            gfam::IFamilyDistanceConstraint* pDistanceConstraintHeight = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordYOZ
                , pReferencePlaneBottom->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
                , pReferencePlaneTopBottomCenter->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
            pDistanceConstraintHeight->CalcDimValue();

            gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
            const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
            pDistanceConstraintHeight->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
        }

        // 截面宽度
        if (pReferencePlaneFrontBackCenter)
        {
            Vector3d dimPosition(0, 0, FamilyTemplateConst::CommonExtend);
            gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
            gfam::IFamilyDistanceConstraint* pDistanceConstraintWidth = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordYOZ
                , pReferencePlaneBack->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
                , pReferencePlaneFront->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
            pDistanceConstraintWidth->CalcDimValue();

            gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
            const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionWidthBuiltInParameter));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
            pDistanceConstraintWidth->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());

            Vector3d dimPositionEqual(0, 0, -secHeight - FamilyTemplateConst::CommonExtend);
            IFamilyMultiDistanceDimension* pDimEqual = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPositionEqual, FamilyTemplateConst::DimScale, ElementId(), ElementId(), coordYOZ, true);
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pReferencePlaneFront->GetElementId(), GraphicsNodeId(1));
            pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
            pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pReferencePlaneBack->GetElementId(), GraphicsNodeId(1));
            pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

            IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDbDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), coordYOZ);
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pReferencePlaneFront->GetElementId(), GraphicsNodeId(1));
            pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
            pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pReferencePlaneBack->GetElementId(), GraphicsNodeId(1));
            pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
            pEqualConstraint->SetRatioValue(0.5);

            pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
        }
    }
}

void gcmp::FamStructureTemplateUtility::InitRectangleColumnFamilyDocument(gcmp::IDocument *pDbDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");

    bool bOk = FamStructureTemplateDocument::InitColumnTemplateFamilyDocument(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(bOk, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 截面形状
    StructureInstanceSectionShapeType sectionType = StructureInstanceSectionShapeType::SECTION_SHAPE_RECTANGLE;
    bool result = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create((int)sectionType), PARAMETER_UID(SectionShapeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 创建形体
    CreateRectangleColumnBody(pDbDoc);
}

void gcmp::FamStructureTemplateUtility::InitCircleColumnFamilyDocument(gcmp::IDocument *pDbDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 结构类型参数
    bool result = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create((int)StructureType::CastInPlaceConcrete), PARAMETER_UID(StructureTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"创建结构类型参数失败",L"GDMPLab",L"2024-03-30");

    //设置放置类型
    const IFamilyParameterDefinition* pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnLevel));

    // 高度参数
    double height = 3000;
    result = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(height), PARAMETER_UID(ColumnHeightBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"柱高度参数添加失败",L"GDMPLab",L"2024-03-30");

    // 截面形状
    StructureInstanceSectionShapeType sectionType = StructureInstanceSectionShapeType::SECTION_SHAPE_CIRCLE;
    result = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create((int)sectionType), PARAMETER_UID(SectionShapeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 截面高度
    double sectionDiameter = 600;
    result = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(sectionDiameter), PARAMETER_UID(CircSectionDiameterBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"柱截面高度参数添加失败",L"GDMPLab",L"2024-03-30");

    // 倾斜角度
    double angle = 0;
    result = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(angle), PARAMETER_UID(ColumnAngleBuiltInParameter), true, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Angle);
    DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"柱倾斜角度参数添加失败",L"GDMPLab",L"2024-03-30");

    // 创建形体
    CreateCircleColumnBody(pDbDoc);
}

void gcmp::FamStructureTemplateUtility::CreateBuiltInWallBody(gcmp::IDocument* pDoc, const gcmp::UniIdentity thicknessParamUid, bool isVariableSectionWall /*= false*/)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    std::vector<IElement*> allRefPlaneEles = pDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_REFERENCE_PLANE);
    std::vector<IReferencePlane*> allRefPlanes;
    FOR_EACH(pItem, allRefPlaneEles)
    {
        IReferencePlane* pRefPlane = quick_cast<IReferencePlane>(pItem);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pRefPlane != nullptr, L"pRefPlane为空",L"GDMPLab",L"2024-03-30");
        allRefPlanes.push_back(pRefPlane);
    }
    IReferencePlane* pReferencePlaneLeft = GetReferencePlane(allRefPlanes, FAMILY_LEFT_RIGHT_CENTER_REFERENCE_PLANE_NAME);
    IReferencePlane* pReferencePlaneBottom = GetReferencePlane(allRefPlanes, FAMILY_TOP_BOTTOM_CENTER_REFERENCE_PLANE_NAME);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneLeft && pReferencePlaneBottom, L"参照平面获取失败！",L"GDMPLab",L"2024-03-30");
    IReferencePlane* pReferencePlaneTop = GetReferencePlane(allRefPlanes, FAMILY_TOP_REFERENCE_PLANE_NAME);
    IReferencePlane* pReferencePlaneFront = GetReferencePlane(allRefPlanes, FAMILY_FRONT_REFERENCE_PLANE_NAME);
    IReferencePlane* pReferencePlaneBack = GetReferencePlane(allRefPlanes, FAMILY_BACK_REFERENCE_PLANE_NAME);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneTop && pReferencePlaneFront && pReferencePlaneBack, L"参照平面获取失败！",L"GDMPLab",L"2024-03-30");

    // 轮廓草图，YOZ面
    Coordinate3d coordProfile(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);
    IFamilySketchPlane* profileSketchPlane = IFamilySketchPlane::Create(pDoc, coordProfile);
    DBG_WARN_AND_RETURN_VOID_UNLESS(profileSketchPlane, L"轮廓草图平面创建失败！",L"GDMPLab",L"2024-03-30");
    IFamilySketch2D* profileSketch = IFamilySketch2D::Create(pDoc, profileSketchPlane->GetOwnerElementId());
    DBG_WARN_AND_RETURN_VOID_UNLESS(profileSketch, L"轮廓草图创建失败！",L"GDMPLab",L"2024-03-30");
    profileSketchPlane->SetSketchId(profileSketch->GetOwnerElementId());
    profileSketchPlane->SetReferencePlaneId(pReferencePlaneLeft->GetElementId());

    // 路径草图，XOY面
    Coordinate3d coordPathSketch(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    IFamilySketchPlane* pathSketchPlane = IFamilySketchPlane::Create(pDoc, coordPathSketch);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pathSketchPlane, L"路径草图平面创建失败",L"GDMPLab",L"2024-03-30");
    IFamilySketch2D* pathSketch = IFamilySketch2D::Create(pDoc, pathSketchPlane->GetOwnerElementId());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pathSketch, L"路径草图创建失败！",L"GDMPLab",L"2024-03-30");
    pathSketchPlane->SetSketchId(pathSketch->GetOwnerElementId());
    pathSketchPlane->SetReferencePlaneId(pReferencePlaneBottom->GetElementId());

    double wallThickness = 200;
    double wallHeight = 3000;
    double wallLength = 4000;
    // 进入草图编辑模式
    //pDoc->SetDocumentEditMode(FamEditModeTypes::SketchModeType);

    // 绘制轮廓线
    {
        IFamily2DSketchLine* profileLines[4] = { nullptr, nullptr, nullptr, nullptr };
        Vector3d vts[4];
        vts[0] = Vector3d(0, -wallThickness / 2, 0);
        vts[1] = Vector3d(0, wallThickness / 2, 0);
        vts[2] = Vector3d(0, wallThickness / 2, wallHeight);
        vts[3] = Vector3d(0, -wallThickness / 2, wallHeight);
        CreateAndAddRectangle(pDoc, profileSketchPlane, profileSketch, vts, profileLines);

        {
            // 矩形的底边线与草图横轴的对齐约束
            OwnerPtr<IGraphicsNodeReference> ref1 = IGraphicsNodeReference::Create(profileSketchPlane->GetOwnerElementId(), GraphicsNodeId(0));
            OwnerPtr<IGraphicsNodeReference> ref2 = IGraphicsNodeReference::Create(profileLines[0]->GetOwnerElementId(), GraphicsNodeId(1));
            FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry, *ref1, *ref2, profileSketchPlane->GetOwnerElementId(),
                profileSketch->GetOwnerElementId(), coordProfile);

            // 矩形的侧边线与草图横轴的垂直约束
            ref2 = IGraphicsNodeReference::Create(profileLines[1]->GetOwnerElementId(), GraphicsNodeId(1));
            FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::Perpendicular, *ref1, *ref2, profileSketchPlane->GetOwnerElementId(),
                profileSketch->GetOwnerElementId(), coordProfile);
        }

        // 厚度方向的距离约束和距离等分约束
        {
            Vector3d dimPosition(0, 0, -FamilyTemplateConst::CommonExtend);
            gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
            gfam::IFamilyDistanceConstraint* pDistanceConstraintWidth = CreateDistanceConstraint(pDoc, dimPosition, FamilyTemplateConst::DimScale, coordProfile
                , profileLines[3]->GetOwnerElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
                , profileLines[1]->GetOwnerElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
            pDistanceConstraintWidth->CalcDimValue();
            pDim->SetAssociatedPlaneId(profileSketchPlane->GetOwnerElementId());
            pDim->SetSketchId(profileSketch->GetOwnerElementId());
            pDistanceConstraintWidth->SetAssociatedPlaneId(profileSketchPlane->GetOwnerElementId());
            pDistanceConstraintWidth->SetSketchId(profileSketch->GetOwnerElementId());
            profileSketch->AddObject(pDim->GetOwnerElementId());
            profileSketch->AddObject(pDistanceConstraintWidth->GetOwnerElementId());

            gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
            const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(thicknessParamUid);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
            pDistanceConstraintWidth->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());

            Vector3d dimPositionEqual(0, 0, wallHeight + FamilyTemplateConst::CommonExtend);
            IFamilyMultiDistanceDimension* pDimEqual = IFamilyMultiDistanceDimension::Create(pDoc, dimPositionEqual, FamilyTemplateConst::DimScale,
                profileSketch->GetOwnerElementId(), profileSketchPlane->GetOwnerElementId(), coordProfile, true);
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(profileLines[1]->GetOwnerElementId(), GraphicsNodeId(1));
            pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(profileSketchPlane->GetOwnerElementId(), GraphicsNodeId(1));
            pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(profileLines[3]->GetOwnerElementId(), GraphicsNodeId(1));
            pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

            IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDoc, profileSketch->GetOwnerElementId(), profileSketchPlane->GetOwnerElementId(),
                pDimEqual->GetOwnerElementId(), coordProfile);
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(profileLines[1]->GetOwnerElementId(), GraphicsNodeId(1));
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(profileSketchPlane->GetOwnerElementId(), GraphicsNodeId(1));
            gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(profileLines[3]->GetOwnerElementId(), GraphicsNodeId(1));
            Vector3d zeroVec(0, 0, 0);
            int ratioSign = FamilyConstraintUtils::CalcRatioSign(pDoc, coordProfile, opRef5.get(), opRef6.get(), opRef7.get(), zeroVec);

            pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
            pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
            pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
            pEqualConstraint->SetRatioValue(0.5 * ratioSign);

            pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
            profileSketch->AddObject(pDimEqual->GetOwnerElementId());
            profileSketch->AddObject(pEqualConstraint->GetOwnerElementId());
        }

        // 高度方向上的距离约束
        {
            Vector3d dimPosition(0, wallThickness * 0.5 + FamilyTemplateConst::CenterExtend, wallHeight * 0.5);
            gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
            gfam::IFamilyDistanceConstraint* pDistanceConstraintHeight = CreateDistanceConstraint(pDoc, dimPosition, FamilyTemplateConst::DimScale, coordProfile
                , profileLines[0]->GetOwnerElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
                , profileLines[2]->GetOwnerElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
            pDistanceConstraintHeight->CalcDimValue();
            pDim->SetAssociatedPlaneId(profileSketchPlane->GetOwnerElementId());
            pDim->SetSketchId(profileSketch->GetOwnerElementId());
            pDistanceConstraintHeight->SetAssociatedPlaneId(profileSketchPlane->GetOwnerElementId());
            pDistanceConstraintHeight->SetSketchId(profileSketch->GetOwnerElementId());
            profileSketch->AddObject(pDim->GetOwnerElementId());
            profileSketch->AddObject(pDistanceConstraintHeight->GetOwnerElementId());

            gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
            const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(WallHeightBuiltInParameter));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
            pDistanceConstraintHeight->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
        }
    }

    // 绘制路径
    {
        Vector3d pts[2];
        pts[0] = Vector3d::Zero;
        pts[1] = Vector3d(wallLength, 0.0, 0.0);
        IFamily2DSketchLine* pLine = IFamily2DSketchLine::Create(pDoc, pathSketch->GetOwnerElementId(), pathSketchPlane->GetOwnerElementId(), pts[0], pts[1]);

        {
            IReferencePlane* pReferencePlaneRight = GetReferencePlane(allRefPlanes, FAMILY_RIGHT_REFERENCE_PLANE_NAME);
            OwnerPtr<IGraphicsNodeReference> gNodeRef1 = IGraphicsNodeReference::Create(pLine->GetOwnerElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::StartPoint);
            OwnerPtr<IGraphicsNodeReference> gNodeRef2 = IGraphicsNodeReference::Create(pLine->GetOwnerElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::EndPoint);
            OwnerPtr<IGraphicsNodeReference> refLeftPlane = IGraphicsNodeReference::Create(pReferencePlaneLeft->GetElementId(), (GraphicsNodeId)1, GraphicsNodeReferenceType::GraphicsNodeSelf);
            OwnerPtr<IGraphicsNodeReference> refRightPlane = IGraphicsNodeReference::Create(pReferencePlaneRight->GetElementId(), (GraphicsNodeId)1, GraphicsNodeReferenceType::GraphicsNodeSelf);
            FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry, *refLeftPlane, *gNodeRef1, pathSketchPlane->GetOwnerElementId(), pathSketch->GetOwnerElementId());
            FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry, *refRightPlane, *gNodeRef2, pathSketchPlane->GetOwnerElementId(), pathSketch->GetOwnerElementId());
        }
    }

    //创建放样体
    IFamilySweep* pSweepWall = nullptr;
    {
        pSweepWall = IFamilySweep::Create(pDoc, pathSketch->GetOwnerElementId(), profileSketch->GetOwnerElementId(), 0);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pSweepWall != nullptr, L"pSweepWall为空! ",L"GDMPLab",L"2024-03-30");
        pSweepWall->GetPathSketch()->SetChildVisible(false);
        pSweepWall->GetProfileSketch()->SetChildVisible(false);
    }

    // 退出草图编辑模式。
    //pDoc->SetDocumentEditMode(L"");

    //设定内外墙面tag
    {
        IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
        const IFamilyParameterDefinition* pWallExteriorFaceParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ExteriorFaceNodeTagBuiltInParameter));
        const IFamilyParameterDefinition* pWallInteriorFaceParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InteriorFaceNodeTagBuiltInParameter));
        pFamilyManager->SetParameterValueStorage(pWallExteriorFaceParameter, TransferOwnership(IParameterValueInt::Create(ExteriorFaceNodeTag)));
        pFamilyManager->SetParameterValueStorage(pWallInteriorFaceParameter, TransferOwnership(IParameterValueInt::Create(InteriorFaceNodeTag)));
    }

    //用参照线的基准平面剪切墙体
    if (isVariableSectionWall)
    {
        std::vector<IElement*> pRefLines = pDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_REFERENCE_LINE);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pRefLines.size() == 1, L"参照线有且只有一条",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_VOID_UNLESS(pRefLines.at(0) != nullptr, L"参照线不能为空",L"GDMPLab",L"2024-03-30");

        std::vector<GraphicsNodeId> refLinePath = { GraphicsNodeId(101), GraphicsNodeId(6) };
        OwnerPtr<IGraphicsNodeReference> ref = IGraphicsNodeReference::Create(pRefLines.at(0)->GetElementId(), refLinePath, GraphicsNodeReferenceType::GraphicsNodeSelf);
        IFamilyPlaneSplitForm* splitForm = IFamilyPlaneSplitForm::Create(pDoc, ref.get(), false, pSweepWall->GetOwnerElementId());
        DBG_WARN_AND_RETURN_VOID_UNLESS(splitForm != nullptr, L"splitForm为空",L"GDMPLab",L"2024-03-30");
        splitForm->SetChildrenVisible(false);
    }
    IRegenerator* pRegenerator = pDoc->GetRegenerator();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pRegenerator != nullptr, L"pRegenerator为空",L"GDMPLab",L"2024-03-30");

    pRegenerator->RegenerateDocument();
}

bool gcmp::FamStructureTemplateUtility::InitCustomizedProfileColumnFamilyDocument(gcmp::IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 结构类型参数
    bool bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)StructureType::CastInPlaceConcrete), PARAMETER_UID(StructureTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建结构类型参数失败",L"GDMPLab",L"2024-03-30");

    // 柱的截面形状
    StructureInstanceSectionShapeType sectionType = StructureInstanceSectionShapeType::SECTION_SHAPE_CUSTOMIZED;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)sectionType), PARAMETER_UID(SectionShapeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建梁模板截面类型参数失败",L"GDMPLab",L"2024-03-30");

    // 设置放置类型
    const IFamilyParameterDefinition* pPlacementTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPlacementTypeDef, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPlacementTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnLevel));

    // 高度参数
    double height = 3000;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(height), PARAMETER_UID(ColumnHeightBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"柱高度参数添加失败",L"GDMPLab",L"2024-03-30");

    // 截面旋转
    double sectionAngle = 0;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(sectionAngle), PARAMETER_UID(SectionRotateAngleBuiltInParameter), true, false, L"", ParameterProcessType::GeneralInput, FamilyParameterType::Angle);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"柱截面旋转参数添加失败",L"GDMPLab",L"2024-03-30");

    // 倾斜角度
    double angle = 0;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(angle), PARAMETER_UID(ColumnAngleBuiltInParameter), true, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Angle);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"柱倾斜角度参数添加失败",L"GDMPLab",L"2024-03-30");

    // 给当前类型命名
    pFamilyManager->RenameCurrentFamilyType(DEFAULT_CUSTOMIZED_PROFILE);

    return true;
}

bool gcmp::FamStructureTemplateUtility::CreateCustomizedProfileColumnBody(IDocument* pDoc, const IPolyCurve* pLoop)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc && pLoop, L"无效参数",L"GDMPLab",L"2024-03-30");

    IFamilySketch2D* pSectionSketch = CreateCustomizedProfileColumnProfileSketch(pDoc, pLoop);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSectionSketch, L"pSectionSketch为空",L"GDMPLab",L"2024-03-30");

    pSectionSketch->SetChildVisible(false);
    IFamilySlopedExtrusion* pSlopedExtrusion = CreateColumnBodyBySlopedExtrusion(pDoc, pSectionSketch);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSlopedExtrusion, L"pSlopedExtrusion为空!",L"GDMPLab",L"2024-03-30");

    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc->GetRegenerator(), L"pDoc->GetRegenerator()为空",L"GDMPLab",L"2024-03-30");
    pDoc->GetRegenerator()->RegenerateDocument();
    return true;
}

bool FamStructureTemplateUtility::InitFloorFamilyDocument(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 结构类型参数
    bool bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)StructureType::CastInPlaceConcrete), PARAMETER_UID(StructureTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 上表面Id参数
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create(FloorTopFaceNodeTag), PARAMETER_UID(FloorTopFaceNodeTagBuiltInParameter), true, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Integer);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");
    // 下表面Id参数
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create(FloorBottomFaceNodeTag), PARAMETER_UID(FloorBottomFaceNodeTagBuiltInParameter), true, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Integer);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 楼板核心层厚度参数
    double thickness = 60;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(thickness), PARAMETER_UID(FloorCoreThicknessBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    const IFamilyParameterDefinition* pCoreThicknessParam = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(FloorCoreThicknessBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCoreThicknessParam != nullptr, L"pCoreThicknessParam为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetFamilyParameterAsDrive(pCoreThicknessParam, true);

    // 楼板在族中的实际厚度参数，比核心层厚度要厚，以确保项目中斜楼板可以正常剖切
    double compensationThickness = 1000;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(compensationThickness), PARAMETER_UID(FloorCompensationThicknessBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 初始化为轮廓族
    gfam::FamilyDocumentUtility::InitFamilyBasedOnProfileFamilyDocument(pDoc);

    pFamilyManager->RenameCurrentFamilyType(DEFAULT_FLOOR_60);
    return true;
}

bool FamStructureTemplateUtility::AddFloorType(IFamilyManager* pFamilyManager, const std::wstring& typeName, double thickness)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    pFamilyManager->AddFamilyType(typeName);
    pFamilyManager->SetCurrentFamilyType(typeName);

    const IFamilyParameterDefinition* pThickness = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(FloorCoreThicknessBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pThickness, L"pThickness为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pThickness, thickness);

    return true;
}

bool gcmp::FamStructureTemplateUtility::CreateFloorBody(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 创建草图
    Coordinate3d coord(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    IFamilySketchPlane* pSketchPlane = IFamilySketchPlane::Create(pDoc, coord);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSketchPlane, L"pSketchPlane为空",L"GDMPLab",L"2024-03-30");
    ElementId sketchPlaneId = pSketchPlane->GetOwnerElementId();
    IFamilySketch2D* pSketch = IFamilySketch2D::Create(pDoc, sketchPlaneId);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSketch, L"pSketch为空",L"GDMPLab",L"2024-03-30");
    ElementId sketchId = pSketch->GetOwnerElementId();
    pSketchPlane->SetSketchId(sketchId);

    double startOffset = -500;
    double endOffset = 500;
    IFamilyExtrusion* pExtrusion = IFamilyExtrusion::Create(pDoc, sketchId, startOffset, endOffset);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pExtrusion != nullptr, L"创建拉伸体失败! ",L"GDMPLab",L"2024-03-30");
    IElement* pOwnerElement = pExtrusion->GetOwnerElement();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pOwnerElement != nullptr, L"pOwnerElement为空？",L"GDMPLab",L"2024-03-30");

    pSketch->SetChildVisible(false);

    // 取出内置参照平面
    DefaultReferencePlanes refPlanes;
    DefaultReferencePlanesOptions refPlaneOptions = TopBottomCenterReferencePlane;
    bool bOk = GetDefaultReferencePlanes(pDoc, refPlaneOptions, refPlanes);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"获取参照平面失败",L"GDMPLab",L"2024-03-30");
    IReferencePlane* pTopBottomCenterPlane = refPlanes.m_pTopBottomCenter;
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pTopBottomCenterPlane, L"pTopBottomCenterPlane为空",L"GDMPLab",L"2024-03-30");

    // 拉伸体厚度约束
    {
        const IFamilyParameterDefinition* pThicknessParam = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(FloorCompensationThicknessBuiltInParameter));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pThicknessParam != nullptr, L"pThicknessParam为空",L"GDMPLab",L"2024-03-30");

        const IFamilySketch2D* pEndFaceSketch = pExtrusion->GetEndfaceSketch();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pEndFaceSketch != nullptr, L"pEndFaceSketch为空",L"GDMPLab",L"2024-03-30");

        DBG_WARN_AND_RETURN_FALSE_UNLESS(pExtrusion->GetTopLocationLine(), L"pExtrusion->GetTopLocationLine()为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pExtrusion->GetBottomLocationLine(), L"pExtrusion->GetBottomLocationLine()为空",L"GDMPLab",L"2024-03-30");
        ElementId topLineId = pExtrusion->GetTopLocationLine()->GetOwnerElementId();
        ElementId bottomLineId = pExtrusion->GetBottomLocationLine()->GetOwnerElementId();

        // 顶面与底面的厚度约束
        {
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pEndFaceSketch->GetSketchPlane(), L"pEndFaceSketch->GetSketchPlane()为空",L"GDMPLab",L"2024-03-30");
            Vector3d dimPos(500, 0, 500);
            IFamilyDistanceConstraint* pTopFaceConstraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, pEndFaceSketch->GetOwnerElementId(),
                pEndFaceSketch->GetSketchPlane()->GetOwnerElementId(), coord,
                bottomLineId, GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
                topLineId, GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pTopFaceConstraint, L"pTopFaceConstraint为空",L"GDMPLab",L"2024-03-30");
            pTopFaceConstraint->SetFamilyParameterDefinitionId(pThicknessParam->GetElementId());
        }

        // 顶面、底面、上下中心面的均分约束
        {
            Vector3d dimPos(1000, 0, 500);
            Coordinate3d coordXOZ(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitZ);
            AddEqualDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, pEndFaceSketch->GetOwnerElementId(),
                pEndFaceSketch->GetSketchPlane()->GetOwnerElementId(), coordXOZ,
                topLineId, GraphicsNodeId(1),
                pTopBottomCenterPlane->GetElementId(), GraphicsNodeId(1),
                bottomLineId, GraphicsNodeId(1));
        }
    }

    //设置拉伸体轮廓
    {
        ElementId instanceTypeId = pFamilyManager->GetBuiltInProfileInstanceType();
        IInstanceType* pInstanceType = quick_cast<IInstanceType>(pDoc->GetElement(instanceTypeId));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceType, L"pInstanceType为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceType->GetBasicInformation(), L"pInstanceType->GetBasicInformation()为空",L"GDMPLab",L"2024-03-30");
        ElementId associatedPlaneId = pTopBottomCenterPlane->GetElementId();
        OwnerPtr<IOnePointInstanceInput> opInput = IOnePointInstanceInput::Create(pDoc, associatedPlaneId, pInstanceType->GetFamilyId(), pInstanceType->GetBasicInformation()->GetName());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(opInput, L"opInput为空",L"GDMPLab",L"2024-03-30");
        opInput->SetPosition(Vector3d::Zero);
        IInstance* pInstanceProfile = IInstance::CreateByOnePoint(opInput.get());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceProfile, L"pInstanceProfile为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceProfile->GetBasicInformation(), L"pInstanceProfile->GetBasicInformation()为空",L"GDMPLab",L"2024-03-30");
        pInstanceProfile->GetBasicInformation()->SetName(GBMP_TR(L"拉伸体轮廓"));

        OwnerPtr<IParameter> referencedParam = pInstanceProfile->GetElementParameters()->GetParameterByUid(PARAMETER_UID(CoordinateSystemBuiltInParameter));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(referencedParam, L"referencedParam为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(IParameter::IsValidParameter(referencedParam), L"没有预期的坐标参数参数",L"GDMPLab",L"2024-03-30");
        IParameterValueCurveByPoints* pPVSEPR = 
            dynamic_cast<IParameterValueCurveByPoints*>(referencedParam->GetParameterValueStorageFw());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pPVSEPR != nullptr, L"没有预期的坐标参数参数",L"GDMPLab",L"2024-03-30");
        referencedParam->SetParameterValueStorage(IParameterValueCurveByPoints::Create());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceProfile->GetElementParameters(), L"pInstanceProfile->GetElementParameters()为空",L"GDMPLab",L"2024-03-30");
        pInstanceProfile->GetElementParameters()->SetParameter(referencedParam.get());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(quick_cast<IFamilyExtrusion>(pExtrusion), L"quick_cast<FamilyExtrusion>(pExtrusion)为空",L"GDMPLab",L"2024-03-30");
        quick_cast<IFamilyExtrusion>(pExtrusion)->SetInstanceIdOfProfileFamily(pInstanceProfile->GetElementId());
    }

    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc->GetRegenerator(), L"pDoc->GetRegenerator()为空",L"GDMPLab",L"2024-03-30");
    pDoc->GetRegenerator()->RegenerateElement(pOwnerElement->GetElementId());

    return true;
}

bool gcmp::FamStructureTemplateUtility::InitPlateHoleFamilyDocument(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    //设置放置类型
    const IFamilyParameterDefinition* pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnHost));

    double plateThickness = 100; // 厚度，实例参数
    bool bOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(plateThickness), PARAMETER_UID(PlateHoleThicknessBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 初始化为轮廓族
    gfam::FamilyDocumentUtility::InitFamilyBasedOnProfileFamilyDocument(pDoc);
    pFamilyManager->RenameCurrentFamilyType(DEFAULT_PLATE_HOLE);
    return true;
}

bool gcmp::FamStructureTemplateUtility::CreatePlateHoleBody(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    //创建草图
    Coordinate3d xoyCoord(Vector3d::Zero, Vector3d::UnitX, Vector3d::NegaUnitY);
    IFamilySketchPlane* sketchPlane = IFamilySketchPlane::Create(pDoc, xoyCoord);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(sketchPlane, L"sketchPlane创建失败！",L"GDMPLab",L"2024-03-30");
    IFamilySketch2D* famSketch = IFamilySketch2D::Create(pDoc, sketchPlane->GetOwnerElementId());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(famSketch, L"famSketch创建失败！",L"GDMPLab",L"2024-03-30");
    sketchPlane->SetSketchId(famSketch->GetOwnerElementId());

    // 进入草图编辑模式。
    ElementId associatedId;
    IFamilyExtrusion* curExtrusion = nullptr;
    IElement* pOwnerElement = nullptr;
    {
        double offset_start = -500;
        double offset_end = 500;
        curExtrusion = IFamilyExtrusion::Create(pDoc, famSketch->GetOwnerElementId(), offset_start, offset_end);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(curExtrusion != nullptr, L"创建拉伸体失败! ",L"GDMPLab",L"2024-03-30");
        pOwnerElement = curExtrusion->GetOwnerElement();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pOwnerElement != nullptr, L"pOwnerElement为空？ ",L"GDMPLab",L"2024-03-30");

        famSketch->SetChildVisible(false);

        // 取出内置参照平面
        DefaultReferencePlanes refPlanes;
        DefaultReferencePlanesOptions refPlaneOptions = TopBottomCenterReferencePlane;
        bool bOk = GetDefaultReferencePlanes(pDoc, refPlaneOptions, refPlanes);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"获取参照平面失败",L"GDMPLab",L"2024-03-30");

        IReferencePlane* pTopBottomCenterPlane = refPlanes.m_pTopBottomCenter;
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pTopBottomCenterPlane, L"pTopBottomCenterPlane为空",L"GDMPLab",L"2024-03-30");
        associatedId = pTopBottomCenterPlane->GetElementId();

        //拉升体上下半部分与中心面约束
        {
            const IFamilySketch2D* pExtrusionSketch = curExtrusion->GetEndfaceSketch();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pExtrusionSketch != nullptr, L"pExtrusionSketch为空",L"GDMPLab",L"2024-03-30");

            //拉伸体厚度 = 楼板厚度
            const gfam::IFamilyParameterDefinition* pHoleThickParam = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(PlateHoleThicknessBuiltInParameter));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pHoleThickParam != nullptr, L"pFloorThickParam为空",L"GDMPLab",L"2024-03-30");

            DBG_WARN_AND_RETURN_FALSE_UNLESS(curExtrusion->GetTopLocationLine(), L"curExtrusion->GetTopLocationLine()为空",L"GDMPLab",L"2024-03-30");
            DBG_WARN_AND_RETURN_FALSE_UNLESS(curExtrusion->GetBottomLocationLine(), L"curExtrusion->GetBottomLocationLine()为空",L"GDMPLab",L"2024-03-30");
            ElementId topLineId = curExtrusion->GetTopLocationLine()->GetOwnerElementId();
            ElementId bottomLineId = curExtrusion->GetBottomLocationLine()->GetOwnerElementId();
            Vector3d dimBottomPos(-200, 0, -250);
            Vector3d dimTopPos(-200, 0, 250);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pExtrusionSketch->GetSketchPlane(), L"pExtrusionSketch->GetSketchPlane()为空",L"GDMPLab",L"2024-03-30");
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pTopBottomCenterPlane->GetBasicInformation(), L"pTopBottomCenterPlane->GetBasicInformation()为空",L"GDMPLab",L"2024-03-30");
            IFamilyDistanceConstraint* pThicknessBottom = AddDistanceConstraint(pDoc, dimBottomPos, FamilyTemplateConst::DimScale, pExtrusionSketch->GetOwnerElementId(), pExtrusionSketch->GetSketchPlane()->GetOwnerElementId(), xoyCoord,
                pTopBottomCenterPlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
                bottomLineId, GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pThicknessBottom, L"pThicknessBottom为空",L"GDMPLab",L"2024-03-30");
            pThicknessBottom->CalcDimValue();
            pThicknessBottom->SetFamilyParameterDefinitionId(pHoleThickParam->GetElementId());
            IFamilyDistanceConstraint* pThicknessTop = AddDistanceConstraint(pDoc, dimTopPos, FamilyTemplateConst::DimScale, pExtrusionSketch->GetOwnerElementId(), pExtrusionSketch->GetSketchPlane()->GetOwnerElementId(), xoyCoord,
                pTopBottomCenterPlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
                topLineId, GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pThicknessTop, L"pThicknessTop为空",L"GDMPLab",L"2024-03-30");
            pThicknessTop->CalcDimValue();
            pThicknessTop->SetFamilyParameterDefinitionId(pHoleThickParam->GetElementId());
        }

    }

    //设置拉伸体轮廓
    {
        ElementId idInstanceType = pFamilyManager->GetBuiltInProfileInstanceType();
        IInstanceType *pInstanceType = quick_cast<IInstanceType>(pDoc->GetElement(idInstanceType));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceType, L"pInstanceType为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceType->GetBasicInformation(), L"pInstanceType->GetBasicInformation()为空",L"GDMPLab",L"2024-03-30");
        OwnerPtr<IOnePointInstanceInput> opInput = IOnePointInstanceInput::Create(pDoc, associatedId, pInstanceType->GetFamilyId(), pInstanceType->GetBasicInformation()->GetName());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(opInput, L"opInput为空",L"GDMPLab",L"2024-03-30");
        opInput->SetPosition(Vector3d::Zero);
        IInstance *pInstanceProfile = IInstance::CreateByOnePoint(opInput.get());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceProfile, L"pInstanceProfile为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceProfile->GetBasicInformation(), L"pInstanceProfile->GetBasicInformation()为空",L"GDMPLab",L"2024-03-30");
        pInstanceProfile->GetBasicInformation()->SetName(GBMP_TR(L"拉伸体轮廓"));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceProfile->GetElementParameters(), L"pInstanceProfile->GetElementParameters()为空",L"GDMPLab",L"2024-03-30");
        OwnerPtr<IParameter> referencedParam = pInstanceProfile->GetElementParameters()->GetParameterByUid(PARAMETER_UID(CoordinateSystemBuiltInParameter));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(referencedParam, L"referencedParam为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(IParameter::IsValidParameter(referencedParam), L"没有预期的坐标参数参数",L"GDMPLab",L"2024-03-30");
        IParameterValueCurveByPoints* pPVSEPR = dynamic_cast<IParameterValueCurveByPoints*>(referencedParam->GetParameterValueStorageFw());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pPVSEPR != nullptr, L"没有预期的坐标参数参数",L"GDMPLab",L"2024-03-30");
        referencedParam->SetParameterValueStorage(IParameterValueCurveByPoints::Create());
        pInstanceProfile->GetElementParameters()->SetParameter(referencedParam.get());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(quick_cast<IFamilyExtrusion>(curExtrusion), L"quick_cast<FamilyExtrusion>(curExtrusion)为空",L"GDMPLab",L"2024-03-30");
        quick_cast<IFamilyExtrusion>(curExtrusion)->SetInstanceIdOfProfileFamily(pInstanceProfile->GetElementId());
    }

    //设置扣减体
    {
        curExtrusion->SetSubstraction(true);
    }

    DBG_WARN_AND_RETURN_FALSE_UNLESS(pOwnerElement->GetDocument(), L"pOwnerElement->GetDocument()为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pOwnerElement->GetDocument()->GetRegenerator(), L"pOwnerElement->GetDocument()->GetRegenerator()为空",L"GDMPLab",L"2024-03-30");
    pOwnerElement->GetDocument()->GetRegenerator()->RegenerateElement(pOwnerElement->GetElementId());
    return true;
}

bool gcmp::FamStructureTemplateUtility::InitRaftFoundationFamilyDocument(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 结构类型参数
    bool bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)StructureType::CastInPlaceConcrete), PARAMETER_UID(StructureTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 筏板厚度参数
    double thickness = 600;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(thickness), PARAMETER_UID(RaftFoundationThicknessBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    const IFamilyParameterDefinition* pThicknessParam = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RaftFoundationThicknessBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pThicknessParam != nullptr, L"pCoreThicknessParam为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetFamilyParameterAsDrive(pThicknessParam, true);

    // Z轴定位线
    int zPositioningType = (int)RaftFoundationZPositioningType::Top;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create(zPositioningType), PARAMETER_UID(RaftFoundationZPositioningTypeBuiltInParameter), true, false, L"", ParameterProcessType::GeneralInput, FamilyParameterType::Integer);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 筏板上表面 与 上下中心面 的偏移值，用于筏板顶面定位
    const std::wstring& zPositioningTypeName = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RaftFoundationZPositioningTypeBuiltInParameter))->GetBasicInformation()->GetName();
    const std::wstring& thicknessName = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RaftFoundationThicknessBuiltInParameter))->GetBasicInformation()->GetName();
    std::wstring topOffsetFormula = zPositioningTypeName + L"*" + thicknessName;

    double topOffset(0.0);
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(topOffset), PARAMETER_UID(RaftFoundationTopPositionOffsetBuiltInParameter), true, true, topOffsetFormula, ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 初始化为轮廓族
    gfam::FamilyDocumentUtility::InitFamilyBasedOnProfileFamilyDocument(pDoc);

    pFamilyManager->RenameCurrentFamilyType(DEFAULT_RAFT_FOUNDATION_600);
    return true;
}

bool gcmp::FamStructureTemplateUtility::AddRaftFoundationType(gfam::IFamilyManager* pFamilyManager, const std::wstring& familyType, double thickness)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    pFamilyManager->AddFamilyType(familyType);
    pFamilyManager->SetCurrentFamilyType(familyType);

    const IFamilyParameterDefinition* pThickness = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RaftFoundationThicknessBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pThickness, L"pThickness为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pThickness, thickness);

    return true;
}

bool gcmp::FamStructureTemplateUtility::CreateRaftFoundationBody(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 创建草图
    Coordinate3d coord(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    IFamilySketchPlane* pSketchPlane = IFamilySketchPlane::Create(pDoc, coord);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSketchPlane, L"pSketchPlane为空",L"GDMPLab",L"2024-03-30");
    ElementId sketchPlaneId = pSketchPlane->GetOwnerElementId();
    IFamilySketch2D* pSketch = IFamilySketch2D::Create(pDoc, sketchPlaneId);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSketch, L"pSketch为空",L"GDMPLab",L"2024-03-30");
    ElementId sketchId = pSketch->GetOwnerElementId();
    pSketchPlane->SetSketchId(sketchId);

    //创建拉伸体
    double startOffset = -500;
    double endOffset = 500;
    IFamilyExtrusion* pExtrusion = IFamilyExtrusion::Create(pDoc, sketchId, startOffset, endOffset);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pExtrusion != nullptr, L"创建拉伸体失败! ",L"GDMPLab",L"2024-03-30");
    IElement* pOwnerElement = pExtrusion->GetOwnerElement();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pOwnerElement != nullptr, L"pOwnerElement为空？ ",L"GDMPLab",L"2024-03-30");

    pSketch->SetChildVisible(false);

    // 取出内置参照平面
    DefaultReferencePlanes refPlanes;
    DefaultReferencePlanesOptions refPlaneOptions = TopBottomCenterReferencePlane;
    bool bOk = GetDefaultReferencePlanes(pDoc, refPlaneOptions, refPlanes);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"获取参照平面失败",L"GDMPLab",L"2024-03-30");
    IReferencePlane* pRefTopBottomCenterPlane = refPlanes.m_pTopBottomCenter;
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pRefTopBottomCenterPlane, L"pRefTopBottomCenterPlane为空",L"GDMPLab",L"2024-03-30");

    // 拉伸体约束
    {
        const IFamilySketch2D* pEndFaceSketch = pExtrusion->GetEndfaceSketch();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pEndFaceSketch != nullptr, L"pEndFaceSketch为空",L"GDMPLab",L"2024-03-30");

        DBG_WARN_AND_RETURN_FALSE_UNLESS(pExtrusion->GetTopLocationLine(), L"pExtrusion->GetTopLocationLine()为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pExtrusion->GetBottomLocationLine(), L"pExtrusion->GetBottomLocationLine()为空",L"GDMPLab",L"2024-03-30");
        ElementId topLineId = pExtrusion->GetTopLocationLine()->GetOwnerElementId();
        ElementId bottomLineId = pExtrusion->GetBottomLocationLine()->GetOwnerElementId();

        // 顶面与底面的厚度约束
        {
            const IFamilyParameterDefinition* pThicknessParam = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RaftFoundationThicknessBuiltInParameter));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pThicknessParam, L"pThicknessParam为空",L"GDMPLab",L"2024-03-30");

            DBG_WARN_AND_RETURN_FALSE_UNLESS(pEndFaceSketch->GetSketchPlane(), L"pEndFaceSketch->GetSketchPlane()为空",L"GDMPLab",L"2024-03-30");
            Vector3d dimPos(500, 0, 500);
            IFamilyDistanceConstraint* pTopBottomFaceConstraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, pEndFaceSketch->GetOwnerElementId(),
                pEndFaceSketch->GetSketchPlane()->GetOwnerElementId(), coord,
                bottomLineId, GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
                topLineId, GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pTopBottomFaceConstraint, L"pTopBottomFaceConstraint为空",L"GDMPLab",L"2024-03-30");
            pTopBottomFaceConstraint->SetFamilyParameterDefinitionId(pThicknessParam->GetElementId());
        }

        // 顶面、上下中心面的距离约束
        {
            const IFamilyParameterDefinition* pTopPositionOffsetParam = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RaftFoundationTopPositionOffsetBuiltInParameter));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pTopPositionOffsetParam, L"pTopPositionOffsetParam为空",L"GDMPLab",L"2024-03-30");

            Vector3d dimPos(500, 0, 500);
            IFamilyDistanceConstraint* pTopFaceConstraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, pEndFaceSketch->GetOwnerElementId(),
                pEndFaceSketch->GetSketchPlane()->GetOwnerElementId(), coord,
                pRefTopBottomCenterPlane->GetElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
                topLineId, GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pTopFaceConstraint, L"pTopFaceConstraint为空",L"GDMPLab",L"2024-03-30");
            pTopFaceConstraint->SetFamilyParameterDefinitionId(pTopPositionOffsetParam->GetElementId());
        }
    }

    //设置拉伸体轮廓
    {
        ElementId instanceTypeId = pFamilyManager->GetBuiltInProfileInstanceType();
        IInstanceType* pInstanceType = quick_cast<IInstanceType>(pDoc->GetElement(instanceTypeId));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceType, L"pInstanceType为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceType->GetBasicInformation(), L"pInstanceType->GetBasicInformation()为空",L"GDMPLab",L"2024-03-30");
        ElementId associatedPlaneId = pRefTopBottomCenterPlane->GetElementId();
        OwnerPtr<IOnePointInstanceInput> opInput = IOnePointInstanceInput::Create(pDoc, associatedPlaneId, pInstanceType->GetFamilyId(), pInstanceType->GetBasicInformation()->GetName());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(opInput, L"opInput为空",L"GDMPLab",L"2024-03-30");
        opInput->SetPosition(Vector3d::Zero);
        IInstance* pInstanceProfile = IInstance::CreateByOnePoint(opInput.get());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceProfile, L"pInstanceProfile为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceProfile->GetBasicInformation(), L"pInstanceProfile->GetBasicInformation()为空",L"GDMPLab",L"2024-03-30");
        pInstanceProfile->GetBasicInformation()->SetName(GBMP_TR(L"拉伸体轮廓"));

        OwnerPtr<IParameter> referencedParam = pInstanceProfile->GetElementParameters()->GetParameterByUid(PARAMETER_UID(CoordinateSystemBuiltInParameter));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(referencedParam, L"referencedParam为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(IParameter::IsValidParameter(referencedParam), L"没有预期的坐标参数参数",L"GDMPLab",L"2024-03-30");
        IParameterValueCurveByPoints* pPVSEPR = 
            dynamic_cast<IParameterValueCurveByPoints*>(referencedParam->GetParameterValueStorageFw());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pPVSEPR != nullptr, L"没有预期的坐标参数参数",L"GDMPLab",L"2024-03-30");
        referencedParam->SetParameterValueStorage(IParameterValueCurveByPoints::Create());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceProfile->GetElementParameters(), L"pInstanceProfile->GetElementParameters()为空",L"GDMPLab",L"2024-03-30");
        pInstanceProfile->GetElementParameters()->SetParameter(referencedParam.get());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(quick_cast<IFamilyExtrusion>(pExtrusion), L"quick_cast<FamilyExtrusion>(pExtrusion)为空",L"GDMPLab",L"2024-03-30");
        quick_cast<IFamilyExtrusion>(pExtrusion)->SetInstanceIdOfProfileFamily(pInstanceProfile->GetElementId());
    }
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc->GetRegenerator(), L"pDoc->GetRegenerator()为空",L"GDMPLab",L"2024-03-30");
    pDoc->GetRegenerator()->RegenerateElement(pOwnerElement->GetElementId());
    return true;
}

bool gcmp::FamStructureTemplateUtility::InitRoofFamilyDocument(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 结构类型参数
    bool bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)StructureType::CastInPlaceConcrete), PARAMETER_UID(StructureTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 屋顶自定义参数
    OwnerPtr<IParameterCustomData> opParam = nullptr;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueCustom::Create(TransferOwnership(opParam)), PARAMETER_UID(InputCustomDataBuiltInParameter), true, false, L"", ParameterProcessType::GeneralInput, FamilyParameterType::Internal);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");
    const IFamilyParameterDefinition* pCustomDataParam = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InputCustomDataBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCustomDataParam != nullptr, L"pCoreThicknessParam为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetFamilyParameterAsDrive(pCustomDataParam, true);

    // 屋顶厚度参数
    double thickness = 60;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(thickness), PARAMETER_UID(FloorOrRoofThicknessBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    const IFamilyParameterDefinition* pCoreThicknessParam = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(FloorOrRoofThicknessBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCoreThicknessParam != nullptr, L"pCoreThicknessParam为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetFamilyParameterAsDrive(pCoreThicknessParam, true);

    pFamilyManager->RenameCurrentFamilyType(DEFAULT_ROOF_60);

    return true;
}

bool gcmp::FamStructureTemplateUtility::AddRoofType(gfam::IFamilyManager* pFamilyManager, const std::wstring& familyType, double thickness)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    pFamilyManager->AddFamilyType(familyType);
    pFamilyManager->SetCurrentFamilyType(familyType);

    const IFamilyParameterDefinition* pThickness = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(FloorOrRoofThicknessBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pThickness, L"pThickness为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pThickness, thickness);

    return true;
}

bool gcmp::FamStructureTemplateUtility::CreateRoofBody(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    IFamilySketchPlane* pSketchPlane = IFamilySketchPlane::Create(pDoc, Coordinate3d());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSketchPlane, L"pSketchPlane为空",L"GDMPLab",L"2024-03-30");

    IFamilySketch2D* pSketch = IFamilySketch2D::Create(pDoc, pSketchPlane->GetOwnerElementId());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSketch, L"pSketch为空",L"GDMPLab",L"2024-03-30");

    pSketchPlane->SetSketchId(pSketch->GetOwnerElementId());
    IElement *pFamRoof = GmArchitectureFamilyUtils::CreateRoof(pDoc, pSketch->GetOwnerElementId());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamRoof, L"pFamRoof为空",L"GDMPLab",L"2024-03-30");

    double length = 1500;

    Vector3d vts[4];
    vts[0] = Vector3d(-length * 0.5, -length * 0.5, 0);
    vts[1] = Vector3d(length * 0.5, -length * 0.5, 0);
    vts[2] = Vector3d(length * 0.5, length * 0.5, 0);
    vts[3] = Vector3d(-length * 0.5, length * 0.5, 0);
    for (int i = 0; i < 4; ++i)
    {
        IFamily2DSketchLine* pFam2DSketchCurve = IFamily2DSketchLine::Create(pDoc, pSketch->GetOwnerElementId(), pSketchPlane->GetOwnerElementId(), vts[i], vts[(i + 1) % 4]);
        DBG_WARN_AND_CONTINUE_UNLESS(pFam2DSketchCurve, L"pFam2DSketchCurve为空",L"GDMPLab",L"2024-03-30");
        pFam2DSketchCurve->GetOwnerElement()->GetBasicInformation()->SetCategoryUid(BuiltInCategoryUniIdentities::BICU_SKETCH_ROOF_BOUNDARY_CURVE);
    }
    pSketch->SetChildVisible(false);
    return true;
}

bool gcmp::FamStructureTemplateUtility::InitRectWallHoleFamilyDocument(gcmp::IDocument* pDbDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDbDoc, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    const IFamilyParameterDefinition* pCoordDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(CoordinateSystemBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCoordDef != nullptr, L"CoordinateSystemBuiltInParameter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pCoordDef, IParameterValueCurveByPoints::Create());

    //设置放置类型
    const IFamilyParameterDefinition* pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnHost));

    double profileWidth = 1000; // 宽度，类型参数
    bool bOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(profileWidth), PARAMETER_UID(RectSectionWidthBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 设宽度参数为驱动参数
    const IFamilyParameterDefinition* pWallholeWidthParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionWidthBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pWallholeWidthParamDef, L"宽度参数不存在",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetFamilyParameterAsDrive(pWallholeWidthParamDef, true);

    double profileHeight = 2000; // 高度，类型参数
    bOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(profileHeight), PARAMETER_UID(RectSectionHeightBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    double wallholeThickness = 200; // 厚度，实例参数
    bOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(wallholeThickness), PARAMETER_UID(WallHoleThicknessBuiltInParameter), true, false, L"", ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 设厚度参数为驱动参数
    const IFamilyParameterDefinition* pWallholeThicknessParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(WallHoleThicknessBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pWallholeThicknessParamDef, L"厚度参数不存在",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetFamilyParameterAsDrive(pWallholeThicknessParamDef, true);

    // Z轴定位线
    int zPositioningType = (int)WallHoleZPositioningType::Center;
    bOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(zPositioningType), PARAMETER_UID(WallHoleZPositioningTypeBuiltInParameter), true, false, L"", ParameterProcessType::GeneralInput, FamilyParameterType::Integer);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 墙洞底面与上下中心面的偏移值，用于墙洞竖直定位
    const std::wstring& zPositioningTypeName = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(WallHoleZPositioningTypeBuiltInParameter))->GetBasicInformation()->GetName();
    const std::wstring& profileHeightName = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter))->GetBasicInformation()->GetName();
    std::wstring bottomOffsetFormula;
    {
        bottomOffsetFormula = L"-0.5*(1-" + zPositioningTypeName + L")*" + profileHeightName;
    }
    double bottomOffset(0.0);
    {
        bottomOffset = -0.5*profileHeight;
    }
    bOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(bottomOffset), PARAMETER_UID(WallHoleBottomOffsetBuiltInParameter), true, true, bottomOffsetFormula, ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 给当前类型命名
    pFamilyManager->RenameCurrentFamilyType(DEFAULT_WALL_HOLE_1000_2000);

    return true;
}

bool gcmp::FamStructureTemplateUtility::CreateRectWallHoleBody(IDocument* pDbDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDbDoc, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    gcmp::IModelView* pModelView = GbmpModelViewUtil::FindViewByBuiltinIndex(pDbDoc, BMVI_Front);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");

    Coordinate3d frontCoord = GbmpModelViewUtil::GetWorkPlaneCoordinate(pModelView);
    IFamilySketchPlane* pSketchPlane = IFamilySketchPlane::Create(pDbDoc, frontCoord);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSketchPlane, L"pSketchPlane为空",L"GDMPLab",L"2024-03-30");

    ElementId sketchPlaneModelId = pSketchPlane->GetOwnerElementId();
    IFamilySketch2D* pSketch = IFamilySketch2D::Create(pDbDoc, sketchPlaneModelId);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSketch, L"pSketch为空",L"GDMPLab",L"2024-03-30");

    ElementId sketchModelId = pSketch->GetOwnerElementId();
    pSketchPlane->SetSketchId(sketchModelId);

    // 进入草图编辑模式
    //pDbDoc->SetDocumentEditMode(FamEditModeTypes::SketchModeType);

    {
        std::vector<IReferencePlane *> referencePlanes;
        ReferencePlaneUtils::GetVisibleReferencePlanes(pDbDoc, frontCoord, referencePlanes);
        // 前视图内置参照平面
        IReferencePlane * pLeftRightCenterPlane = GetReferencePlane(referencePlanes, FAMILY_LEFT_RIGHT_CENTER_REFERENCE_PLANE_NAME);
        IReferencePlane * pTopBottomCenterPlane = GetReferencePlane(referencePlanes, FAMILY_TOP_BOTTOM_CENTER_REFERENCE_PLANE_NAME);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pLeftRightCenterPlane && pTopBottomCenterPlane, L"pLeftRightCenterPlane && pTopBottomCenterPlane为空",L"GDMPLab",L"2024-03-30");

        // 生成矩形轮廓
        IFamily2DSketchLine* pRectLine[4] = { nullptr, nullptr, nullptr, nullptr }; // 0 宽度方向，1 高度方向
        {
            Vector3d vts[4];
            vts[0] = Vector3d(-750, 0, 1000);
            vts[1] = Vector3d(750, 0, 1000);
            vts[2] = Vector3d(750, 0, -1000);
            vts[3] = Vector3d(-750, 0, -1000);
            CreateRectangle(pDbDoc, pSketchPlane, pSketch, vts, pRectLine);
        }

        //// 矩形的下端线与上下中心面对齐
        //{
        //    FamilyConstraintUtils::AddConstraint(pDbDoc, FamilyConstraintType::AlignGeometry, pRectLine[2]->GetElementId(), FamilyConstraintReferenceType::Self, pTopBottomCenterPlane->GetElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);
        //}
        // 截面底部偏移
        {
            Vector3d dimPos(-1000, 0, -275);
            gfam::IFamilyDistanceConstraint* pBottomOffsetConstraint = AddDistanceConstraint(pDbDoc, dimPos, FamilyTemplateConst::DimScale, sketchModelId, sketchPlaneModelId, frontCoord,
                pRectLine[2]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
                pTopBottomCenterPlane, GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);

            const IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(WallHoleBottomOffsetBuiltInParameter));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");

            pBottomOffsetConstraint->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
        }

        // 宽度约束
        {
            Vector3d dimPos(0, 0, 1500);
            IFamilyDistanceConstraint* pWidthConstraint = AddDistanceConstraint(pDbDoc, dimPos, FamilyTemplateConst::DimScale, sketchModelId, sketchPlaneModelId, frontCoord,
                pRectLine[3]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
                pRectLine[1]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
            pWidthConstraint->CalcDimValue();

            const IFamilyParameterDefinition* pWidthParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionWidthBuiltInParameter));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pWidthParameter, L"pWidthParameter为空",L"GDMPLab",L"2024-03-30");
            pWidthConstraint->SetFamilyParameterDefinitionId(pWidthParameter->GetElementId());
        }
        // 高度约束
        {
            Vector3d dimPos(1000, 0, 0);
            IFamilyDistanceConstraint* pHeightConstraint = AddDistanceConstraint(pDbDoc, dimPos, FamilyTemplateConst::DimScale, sketchModelId, sketchPlaneModelId, frontCoord,
                pRectLine[0]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
                pRectLine[2]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
            pHeightConstraint->CalcDimValue();

            const IFamilyParameterDefinition* pHeightParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pHeightParameter, L"pHeightParameter为空",L"GDMPLab",L"2024-03-30");
            pHeightConstraint->SetFamilyParameterDefinitionId(pHeightParameter->GetElementId());
        }

        // 创建扣减体（拉伸体）
        double offset_start = -150;
        double offset_end = 150;
        IFamilyExtrusion* pExtrusion = IFamilyExtrusion::Create(pDbDoc, pSketch->GetOwnerElementId(), offset_start, offset_end);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pExtrusion, L"pExtrusion为空",L"GDMPLab",L"2024-03-30");
        IElement* pOwnerElement = pExtrusion->GetOwnerElement();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pOwnerElement, L"pOwnerElement为空",L"GDMPLab",L"2024-03-30");


        pSketch->SetChildVisible(false);
        pExtrusion->SetSubstraction(true);

        // 拉伸体约束（墙厚）
        {
            // 关联更新一次，才能拿到GBody
            pOwnerElement->GetDocument()->GetRegenerator()->RegenerateElement(pOwnerElement->GetElementId());

            const IGraphicsBRepBody* pExtrusionBody = pExtrusion->GetGraphicsBRepBody();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pExtrusionBody, L"无法得到拉伸体的Gbody",L"GDMPLab",L"2024-03-30");
            const IFamilySketchCurve* pBottomLine = quick_cast<IFamilySketch2D>(pExtrusion->GetEndfaceSketch())->GetLocationLineByName(IFamilyExtrusion::BottomLocationLineName);
            const IFamilySketchCurve* pTopLine = quick_cast<IFamilySketch2D>(pExtrusion->GetEndfaceSketch())->GetLocationLineByName(IFamilyExtrusion::TopLocationLineName);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pBottomLine && pTopLine, L"pBottomLine && pTopLine为空",L"GDMPLab",L"2024-03-30");
            IFamilySketch2D* pEndFaceSketch = pExtrusion->GetEndfaceSketch();
            const IFamilySketchPlane* pEndFaceSketchPlane = pExtrusion->GetEndfaceSketch()->GetSketchPlane();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pEndFaceSketch && pEndFaceSketchPlane, L"pEndFaceSketch && pEndFaceSketchPlane为空",L"GDMPLab",L"2024-03-30");

            gcmp::IModelView* pBaseModelView = GbmpModelViewUtil::FindViewByBuiltinIndex(pDbDoc, BMVI_BaseLevel);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pBaseModelView, L"pBaseModelView为空",L"GDMPLab",L"2024-03-30");
            Coordinate3d baseCoord = GbmpModelViewUtil::GetWorkPlaneCoordinate(pBaseModelView);

            std::vector<IReferencePlane *> referencePlanes;
            ReferencePlaneUtils::GetVisibleReferencePlanes(pDbDoc, baseCoord, referencePlanes);
            // 基础平面视图内置参照平面
            IReferencePlane * pFrontBackCenterPlane = GetReferencePlane(referencePlanes, FAMILY_FRONT_BACK_CENTER_REFERENCE_PLANE_NAME);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pFrontBackCenterPlane, L"pFrontBackCenterPlane为空",L"GDMPLab",L"2024-03-30");

            // 厚度约束
            {
                Vector3d dimPos(0, 0, 2500);
                double scale = 500.0;
                IFamilyDistanceConstraint* pThicknessConstraint = AddDistanceConstraint(pDbDoc, dimPos, scale, pEndFaceSketch->GetOwnerElementId(), pEndFaceSketchPlane->GetOwnerElementId(), baseCoord,
                    pBottomLine->GetOwnerElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
                    pTopLine->GetOwnerElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
                pThicknessConstraint->CalcDimValue();

                const IFamilyParameterDefinition* pThicknessParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(WallHoleThicknessBuiltInParameter));
                DBG_WARN_AND_RETURN_FALSE_UNLESS(pThicknessParameter, L"pThicknessParameter为空",L"GDMPLab",L"2024-03-30");
                pThicknessConstraint->SetFamilyParameterDefinitionId(pThicknessParameter->GetElementId());
            }

            // 与前后参考面等分约束
            {
                Vector3d dimPos(0, 0, 1000);
                double scale = 500.0;
                AddEqualDistanceConstraint(pDbDoc, dimPos, scale, pEndFaceSketch->GetOwnerElementId(), pEndFaceSketchPlane->GetOwnerElementId(), pEndFaceSketchPlane->GetPlane(),
                    pTopLine->GetOwnerElementId(), GraphicsNodeId(1), pFrontBackCenterPlane->GetElementId(), GraphicsNodeId(1), pBottomLine->GetOwnerElementId(), GraphicsNodeId(1));
            }
        }
    }

    return true;
}

bool FamStructureTemplateUtility::AddRectWallHoleType(IFamilyManager* pFamilyManager, const std::wstring& familyType, double profileWidth, double profileHeight)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    pFamilyManager->AddFamilyType(familyType);
    pFamilyManager->SetCurrentFamilyType(familyType);

    const IFamilyParameterDefinition* pPDColumnProfileWidth = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionWidthBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPDColumnProfileWidth != nullptr, L"无法获得截面宽度参数",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pPDColumnProfileWidth, profileWidth);

    const IFamilyParameterDefinition* pPDColumnProfileHeight = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPDColumnProfileHeight != nullptr, L"无法获得截面高度参数",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pPDColumnProfileHeight, profileHeight);

    return true;
}

void gcmp::FamStructureTemplateUtility::CreateSweepBody(gcmp::IDocument *pDoc, bool isVariableSection)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    DefaultReferencePlanes refPlanes;
    DefaultReferencePlanesOptions refPlaneOptions = (DefaultReferencePlanesOptions)(LeftRightCenterReferencePlane
        | TopBottomCenterReferencePlane | TopReferencePlane | FrontReferencePlane | BackReferencePlane | RightReferencePlane);
    bool result = GetDefaultReferencePlanes(pDoc, refPlaneOptions, refPlanes);
    DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"获取参照平面失败",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(refPlanes.m_pLeftRightCenter && refPlanes.m_pTopBottomCenter && refPlanes.m_pRight, L"参照平面获取失败！",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(refPlanes.m_pTop && refPlanes.m_pFront && refPlanes.m_pBack, L"参照平面获取失败！",L"GDMPLab",L"2024-03-30");

    // 轮廓草图，YOZ面
    Coordinate3d coordProfile(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);
    IFamilySketchPlane* profileSketchPlane = IFamilySketchPlane::Create(pDoc, coordProfile);
    DBG_WARN_AND_RETURN_VOID_UNLESS(profileSketchPlane, L"轮廓草图平面创建失败！",L"GDMPLab",L"2024-03-30");
    IFamilySketch2D* profileSketch = IFamilySketch2D::Create(pDoc, profileSketchPlane->GetOwnerElementId());
    DBG_WARN_AND_RETURN_VOID_UNLESS(profileSketch, L"轮廓草图创建失败！",L"GDMPLab",L"2024-03-30");
    profileSketchPlane->SetSketchId(profileSketch->GetOwnerElementId());
    profileSketchPlane->SetReferencePlaneId(refPlanes.m_pLeftRightCenter->GetElementId());

    // 路径草图，XOY面
    Coordinate3d coordPathSketch(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    IFamilySketchPlane* pathSketchPlane = IFamilySketchPlane::Create(pDoc, coordPathSketch);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pathSketchPlane, L"路径草图平面创建失败",L"GDMPLab",L"2024-03-30");
    IFamilySketch2D* pathSketch = IFamilySketch2D::Create(pDoc, pathSketchPlane->GetOwnerElementId());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pathSketch, L"路径草图创建失败！",L"GDMPLab",L"2024-03-30");
    pathSketchPlane->SetSketchId(pathSketch->GetOwnerElementId());
    pathSketchPlane->SetReferencePlaneId(refPlanes.m_pTopBottomCenter->GetElementId());

    // 进入草图编辑模式
    //pDoc->SetDocumentEditMode(FamEditModeTypes::SketchModeType);

    // 绘制轮廓线
    {
        // 创建矩形轮廓
        IFamily2DSketchLine* profileLines[4] = { nullptr, nullptr, nullptr, nullptr };
        Vector3d vts[4] = { Vector3d::NegaUnitY, Vector3d::UnitY, Vector3d(0, 1, 1), Vector3d(0, -1, 1) };
        CreateAndAddRectangle(pDoc, profileSketchPlane, profileSketch, vts, profileLines);

        // 轮廓四条边对齐四个关联平面
        CreateAlignConstraint(pDoc, refPlanes.m_pTopBottomCenter, profileLines[0], profileSketchPlane);
        CreateAlignConstraint(pDoc, refPlanes.m_pBack, profileLines[1], profileSketchPlane);
        CreateAlignConstraint(pDoc, refPlanes.m_pTop, profileLines[2], profileSketchPlane);
        CreateAlignConstraint(pDoc, refPlanes.m_pFront, profileLines[3], profileSketchPlane);
    }

    // 绘制路径
    {
        IFamily2DSketchLine* pLine = IFamily2DSketchLine::Create(pDoc, pathSketch->GetOwnerElementId(), pathSketchPlane->GetOwnerElementId(), Vector3d::Zero, Vector3d::UnitX);
        bool result = CreateStartEndPtAlignConstraints(pDoc, refPlanes.m_pLeftRightCenter, refPlanes.m_pRight, pLine, pathSketchPlane);
        DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"绘制路径线端点约束创建失败",L"GDMPLab",L"2024-03-30");
    }

    //创建放样体
    IFamilySweep* pSweepWall = nullptr;
    {
        pSweepWall = IFamilySweep::Create(pDoc, pathSketch->GetOwnerElementId(), profileSketch->GetOwnerElementId(), 0);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pSweepWall != nullptr, L"pSweepWall为空! ",L"GDMPLab",L"2024-03-30");
        pSweepWall->GetPathSketch()->SetChildVisible(false);
        pSweepWall->GetProfileSketch()->SetChildVisible(false);

        if(DEBUG_MODE(RotateFaceTexture))
        {
            IGraphicsMaterialManager* pMaterialMgr = pDoc->GetGraphicsMaterialManager();
            if (pMaterialMgr)
            {
                ElementId materialId = pMaterialMgr->CreateGraphicsMaterialFromLocalLibrary(L"Wood-02");
                pSweepWall->SetGraphicsMaterialId(materialId);

                GraphicsNodeId nodeId1 = GraphicsNodeId::Create(4);
                GraphicsNodeId nodeId2 = GraphicsNodeId::Create(6);

                std::map<gcmp::GraphicsNodeId, double> faceTextureRotationMap;
                faceTextureRotationMap.insert(std::make_pair(nodeId1, 45));
                faceTextureRotationMap.insert(std::make_pair(nodeId2, 45));
                pSweepWall->SetFaceTextureRotationMap(faceTextureRotationMap);
            }
        }
    }

    // 退出草图编辑模式。
    //pDoc->SetDocumentEditMode(L"");

    //用参照线的基准平面剪切墙体
    if (isVariableSection)
    {
        bool result = GetDefaultReferencePlanes(pDoc, FrontBackCenterReferencePlane, refPlanes);
        DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"获取关联平面失败",L"GDMPLab",L"2024-03-30");
        IFamilyPlaneSplitForm* splitForm = CutVariableSectionBody(pDoc, pSweepWall, refPlanes.m_pFrontBackCenter, refPlanes.m_pTopBottomCenter, refPlanes.m_pLeftRightCenter, refPlanes.m_pRight);
        DBG_WARN_AND_RETURN_VOID_UNLESS(splitForm, L"SweepBody裁剪失败",L"GDMPLab",L"2024-03-30");
    }

    FamilySolverResult solveResult = FamilySolverUtils::SolveSketchOrDocument(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(solveResult == FamilySolverResult::Ok, L"约束解算失败" + StringUtil::ToWString((int)solveResult),L"GDMPLab",L"2024-03-30");
    pDoc->GetRegenerator()->RegenerateDocument();
}

bool gcmp::FamStructureTemplateUtility::AddVariableSectionWallParameters(gcmp::IDocument *pDbDoc, gfam::IFamilyManager* pFamilyManager)
{
    //墙长度，变截面墙的长度参数需要用来驱动参照平面，只能放在族里实现，直墙长度需要支持圆弧，所以放到项目实现
    double dLength = 4000;
    bool bRes = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(dLength), PARAMETER_UID(LineFamilyLengthBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bRes, L"创建墙模板参数有问题",L"GDMPLab",L"2024-03-30");

    //墙的起点底偏移
    double startBottomOffset = 0.0;
    bool isOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(startBottomOffset), PARAMETER_UID(WallStartBottomOffsetBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(isOk, L"创建墙模板参数有问题",L"GDMPLab",L"2024-03-30");

    //墙的终点底偏移
    double endBottomOffset = 0.0;
    isOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(endBottomOffset), PARAMETER_UID(WallEndBottomOffsetBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(isOk, L"创建墙模板参数有问题",L"GDMPLab",L"2024-03-30");

    //墙的起点墙高度
    double startWallHeight = 2000;
    isOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(startWallHeight), PARAMETER_UID(WallStartHeightBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(isOk, L"创建墙模板参数有问题",L"GDMPLab",L"2024-03-30");

    //墙的终点墙高度
    double endWallHeight = 2500;
    isOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(endWallHeight), PARAMETER_UID(WallEndHeightBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(isOk, L"创建墙模板参数有问题",L"GDMPLab",L"2024-03-30");

    //最大墙高度
    double maxWallHeight = 2500;
    isOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(maxWallHeight), PARAMETER_UID(VariableSectionWallMaxHeightBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(isOk, L"创建墙模板参数有问题",L"GDMPLab",L"2024-03-30");

    // 起点顶高度
    std::wstring strStartTopHeight = PARAMETER_DEF(WallStartBottomOffsetBuiltInParameter)->GetName() + L" + " + PARAMETER_DEF(WallStartHeightBuiltInParameter)->GetName();

    IFamilyParameterDefinition* pStartTopHeightParam = IFamilyParameterDefinition::Create(pDbDoc, L"StartTopHeight", FamilyParameterType::Length, true, strStartTopHeight);
    pStartTopHeightParam->SetUnitTypeId(UNIT(Length));
    pStartTopHeightParam->SetParameterTypeId(PARAMETER_TYPE(None));

    pFamilyManager->AddFamilyParameterDefinition(pStartTopHeightParam);

    
    // 终点顶高度
    std::wstring strEndTopHeight = PARAMETER_DEF(WallEndBottomOffsetBuiltInParameter)->GetName() + L" + " + PARAMETER_DEF(WallEndHeightBuiltInParameter)->GetName();
    
    IFamilyParameterDefinition* pEndTopHeightParam = IFamilyParameterDefinition::Create(pDbDoc, L"EndTopHeight", FamilyParameterType::Length, true, strEndTopHeight);
    pEndTopHeightParam->SetUnitTypeId(UNIT(Length));
    pEndTopHeightParam->SetParameterTypeId(PARAMETER_TYPE(None));

    pFamilyManager->AddFamilyParameterDefinition(pEndTopHeightParam);
    
    // 起点底高度
    std::wstring strStartBottomHeight = PARAMETER_DEF(WallStartBottomOffsetBuiltInParameter)->GetName();
    
    IFamilyParameterDefinition* pStartBottomParam = IFamilyParameterDefinition::Create(pDbDoc, L"StartBottomHeight", FamilyParameterType::Length, true, strStartBottomHeight);
    pStartBottomParam->SetUnitTypeId(UNIT(Length));
    pStartBottomParam->SetParameterTypeId(PARAMETER_TYPE(None));

    pFamilyManager->AddFamilyParameterDefinition(pStartBottomParam);
    
    // 终点底高度
    std::wstring strEndBottomHeight = PARAMETER_DEF(WallEndBottomOffsetBuiltInParameter)->GetName();
    //pFamilyManager->AddFamilyParameterDefinition(L"EndBottomHeight", FamilyParameterType::Length, ParameterStorageType::Double, UNIT(Length), PARAMETER_TYPE(None), true, true, strEndBottomHeight);

    IFamilyParameterDefinition* pEndBottomParam = IFamilyParameterDefinition::Create(pDbDoc, L"EndBottomHeight", FamilyParameterType::Length, true, strEndBottomHeight);
    pEndBottomParam->SetUnitTypeId(UNIT(Length));
    pEndBottomParam->SetParameterTypeId(PARAMETER_TYPE(None));

    pFamilyManager->AddFamilyParameterDefinition(pEndBottomParam);

    const IFamilyParameterDefinition* pWallHeightParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(VariableSectionWallMaxHeightBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pWallHeightParamDef != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
    std::wstring strWallHeight = L"if(" + pStartTopHeightParam->GetBasicInformation()->GetName() + L">" + pEndTopHeightParam->GetBasicInformation()->GetName() + L"," + pStartTopHeightParam->GetBasicInformation()->GetName() + L"," + pEndTopHeightParam->GetBasicInformation()->GetName() + L")";
    //pWallHeightParamDef->SetIsDeterminedByFormula(true);
    //pWallHeightParamDef->SetFormula(strWallHeight);
    pFamilyManager->UpdateFamilyParameterDefinition(pWallHeightParamDef, strWallHeight);

    return true;
}

IFamilyPlaneSplitForm *gcmp::FamStructureTemplateUtility::CutVariableSectionBody(gcmp::IDocument *pDbDoc, gfam::IFamilySweep *pSweepBody
    , IReferencePlane *pRefLinePlane, IReferencePlane *pBottomPlane, IReferencePlane *pLeftPlane, IReferencePlane *pRightPlane)
{
    // 创建下切割面切扫略墙体
    IFamilyPlaneSplitForm* splitForm = CutVariableSectionBody(pDbDoc, pSweepBody->GetOwnerElementId(), pRefLinePlane, pBottomPlane, pLeftPlane, pRightPlane
        , L"StartBottomHeight", L"EndBottomHeight", false);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(splitForm, L"创建下切割面切扫略墙体失败",L"GDMPLab",L"2024-03-30");

    // 创建上切割面切扫略墙体
    splitForm = CutVariableSectionBody(pDbDoc, splitForm->GetOwnerElementId(), pRefLinePlane, pBottomPlane, pLeftPlane, pRightPlane
        , L"StartTopHeight", L"EndTopHeight", true);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(splitForm, L"创建上切割面切扫略墙体",L"GDMPLab",L"2024-03-30");

    return splitForm;
}

gfam::IFamilyPlaneSplitForm * gcmp::FamStructureTemplateUtility::CutVariableSectionBody(gcmp::IDocument *pDbDoc, ElementId bodyElementId
    , IReferencePlane *pRefLinePlane, IReferencePlane *pBottomPlane, IReferencePlane *pLeftPlane, IReferencePlane *pRightPlane
    , const std::wstring &startHeightParam, const std::wstring &endHeightParam, bool keepReverse)
{
    gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    //创建参照线
    double startWallHeight = 2000;
    double dLength = 4000;
    IFamilyReferenceLine* pRefLine = IFamilyReferenceLine::CreateAsStraightLine(pDbDoc, pRefLinePlane->GetElementId(), Vector3d::Zero, Vector3d::UnitX);

    // 参照线的起点和上下中心距离约束
    Coordinate3d coordXOZ(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitZ);
    Vector3d dimPosition(-FamilyTemplateConst::CenterExtend, 0, startWallHeight / 2);
    gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
    gfam::IFamilyDistanceConstraint* pDistanceConstraint1 = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOZ
        , pRefLine->GetOwnerElementId(), gcmp::GraphicsNodeReferenceType::StartPoint, gcmp::GraphicsNodeId(1)
        , pBottomPlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
    pDistanceConstraint1->CalcDimValue();
    // 约束参数绑定
    const gfam::IFamilyParameterDefinition* pStartBottomOffsetParamDef = pFamilyManager->GetFamilyParameterDefinition(startHeightParam);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStartBottomOffsetParamDef != nullptr, L"pStartBottomOffsetParamDef为空",L"GDMPLab",L"2024-03-30");
    pDistanceConstraint1->SetFamilyParameterDefinitionId(pStartBottomOffsetParamDef->GetElementId());

    //参照线的终点和上下中心的距离约束
    dimPosition = Vector3d(dLength + FamilyTemplateConst::CenterExtend, 0, startWallHeight / 2);
    gfam::IFamilyDistanceConstraint* pDistanceConstraint2 = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOZ
        , pRefLine->GetOwnerElementId(), gcmp::GraphicsNodeReferenceType::EndPoint, gcmp::GraphicsNodeId(1)
        , pBottomPlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
    pDistanceConstraint2->CalcDimValue();
    // 约束参数绑定
    const gfam::IFamilyParameterDefinition* pEndBottomOffsetParamDef = pFamilyManager->GetFamilyParameterDefinition(endHeightParam);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pEndBottomOffsetParamDef != nullptr, L"pEndBottomOffsetParamDef为空",L"GDMPLab",L"2024-03-30");
    pDistanceConstraint2->SetFamilyParameterDefinitionId(pEndBottomOffsetParamDef->GetElementId());

    // 参照线端点对齐到左右参照平面上
    IFamilyGeometryConstraint *pConstraint = CreateEqualConstraint(pDbDoc, coordXOZ, pLeftPlane, gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, GraphicsNodeId(1), pRefLine->GetOwnerElement(), gcmp::GraphicsNodeReferenceType::StartPoint, GraphicsNodeId(1));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pConstraint, L"创建对齐约束失败",L"GDMPLab",L"2024-03-30");
    pConstraint = CreateEqualConstraint(pDbDoc, coordXOZ, pRightPlane, gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, GraphicsNodeId(1), pRefLine->GetOwnerElement(), gcmp::GraphicsNodeReferenceType::EndPoint, GraphicsNodeId(1));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pConstraint, L"创建对齐约束失败",L"GDMPLab",L"2024-03-30");

    // 切割扫略体

    std::vector<GraphicsNodeId> refLinePath = { GraphicsNodeId(101), GraphicsNodeId(6) };

    OwnerPtr<IGraphicsNodeReference> ref = IGraphicsNodeReference::Create(pRefLine->GetOwnerElementId(), refLinePath, GraphicsNodeReferenceType::GraphicsNodeSelf);
    IFamilyPlaneSplitForm* splitForm = IFamilyPlaneSplitForm::Create(pDbDoc, ref.get(), keepReverse, bodyElementId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(splitForm != nullptr, L"splitForm为空",L"GDMPLab",L"2024-03-30");
    splitForm->SetChildrenVisible(false);

    return splitForm;
}

void gcmp::FamStructureTemplateUtility::CreateRectangleColumnBody(gcmp::IDocument *pDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    DefaultReferencePlanes refPlanes;
    DefaultReferencePlanesOptions refPlaneOptions = (DefaultReferencePlanesOptions)(TopBottomCenterReferencePlane
        | FrontBackCenterReferencePlane | LeftRightCenterReferencePlane);
    bool result = GetDefaultReferencePlanes(pDoc, refPlaneOptions, refPlanes);
    DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"获取参照平面失败",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(refPlanes.m_pTopBottomCenter && refPlanes.m_pFrontBackCenter && refPlanes.m_pLeftRightCenter, L"参照平面获取失败！",L"GDMPLab",L"2024-03-30");

    // 轮廓草图，XOY面
    Coordinate3d coordProfile(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    IFamilySketchPlane* profileSketchPlane = IFamilySketchPlane::Create(pDoc, coordProfile);
    DBG_WARN_AND_RETURN_VOID_UNLESS(profileSketchPlane, L"轮廓草图平面创建失败！",L"GDMPLab",L"2024-03-30");
    IFamilySketch2D* profileSketch = IFamilySketch2D::Create(pDoc, profileSketchPlane->GetOwnerElementId());
    DBG_WARN_AND_RETURN_VOID_UNLESS(profileSketch, L"轮廓草图创建失败！",L"GDMPLab",L"2024-03-30");
    profileSketchPlane->SetSketchId(profileSketch->GetOwnerElementId());
    profileSketchPlane->SetReferencePlaneId(refPlanes.m_pTopBottomCenter->GetElementId());

    // 进入草图编辑模式
    IEditMode::Get(pDoc, L"SketchModeType")->StartEditing(pDoc, profileSketch->GetOwnerElementId(), true, false);

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 绘制轮廓线
    {
        // 创建矩形轮廓
        IFamily2DSketchLine* profileLines[4] = { nullptr, nullptr, nullptr, nullptr };
        Vector3d vts[4] = { Vector3d(-1, -1, 0), Vector3d(1, -1, 0), Vector3d(1, 1, 0), Vector3d(-1, 1, 0) };
        CreateAndAddRectangle(pDoc, profileSketchPlane, profileSketch, vts, profileLines);

        // 创建轮廓约束
        IFamily2DSketchLine* pLeftRightCenterLocationLine = IFamily2DSketchLine::CreateAsReference(pDoc, profileSketch->GetOwnerElementId(), profileSketchPlane->GetOwnerElementId()
            , Vector3d::Zero, Vector3d(0, -1000, 0));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pLeftRightCenterLocationLine, L"pLeftRightCenterLocationLine为空",L"GDMPLab",L"2024-03-30");
        IFamily2DSketchLine* pFrontBackCenterLocationLine = IFamily2DSketchLine::CreateAsReference(pDoc, profileSketch->GetOwnerElementId(), profileSketchPlane->GetOwnerElementId()
            , Vector3d::Zero, Vector3d(-1000, 0, 0));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFrontBackCenterLocationLine, L"pFrontBackCenterLocationLine为空",L"GDMPLab",L"2024-03-30");
        OwnerPtr<IGraphicsNodeReference> refX = IGraphicsNodeReference::Create(pFrontBackCenterLocationLine->GetOwnerElementId(), GraphicsNodeId(1));
        FamilyConstraintUtils::AddPinnedConstraint(pDoc, *refX, profileSketch->GetOwnerElementId(), profileSketchPlane->GetOwnerElementId());
        OwnerPtr<IGraphicsNodeReference> refY = IGraphicsNodeReference::Create(pLeftRightCenterLocationLine->GetOwnerElementId(), GraphicsNodeId(1));
        FamilyConstraintUtils::AddPinnedConstraint(pDoc, *refY, profileSketch->GetOwnerElementId(), profileSketchPlane->GetOwnerElementId());

        // 截面高度约束
        {
            const IFamilyParameterDefinition* pRectHeightParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pRectHeightParamDef, L"柱截面高度参数不存在",L"GDMPLab",L"2024-03-30");
            double sectionWidth = pFamilyManager->GetParameterValueAsDouble(pRectHeightParamDef);
            // 创建截面高度距离约束
            Vector3d dimPosition(-sectionWidth / 2 - FamilyTemplateConst::CommonExtend, 0, 0);
            gfam::IFamilyDistanceConstraint* pDistanceConstraintWidth = CreateDistanceConstraint(pDoc, profileLines[0], profileLines[2]
                , profileSketchPlane, dimPosition);
            // 距离约束绑定到截面高度参数
            pDistanceConstraintWidth->SetFamilyParameterDefinitionId(pRectHeightParamDef->GetElementId());
            // 柱两侧距离X坐标轴等距
            Vector3d dimPositionEqual(sectionWidth / 2 + FamilyTemplateConst::CommonExtend, 0, 0);
            IFamilyDistanceRatioConstraint* pEqualConstraint = CreateEqualConstraint(pDoc, profileLines[0], profileLines[2], pFrontBackCenterLocationLine
                , profileSketchPlane, dimPositionEqual);
        }

        // 截面宽度约束
        {
            const IFamilyParameterDefinition* pRectWidthParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionWidthBuiltInParameter));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pRectWidthParamDef, L"柱截面宽度参数不存在",L"GDMPLab",L"2024-03-30");
            double sectionWidth = pFamilyManager->GetParameterValueAsDouble(pRectWidthParamDef);
            // 创建截面宽度距离约束
            Vector3d dimPosition(0, -sectionWidth / 2 - FamilyTemplateConst::CommonExtend, 0);
            gfam::IFamilyDistanceConstraint* pDistanceConstraintWidth = CreateDistanceConstraint(pDoc, profileLines[1], profileLines[3]
                , profileSketchPlane, dimPosition);

            // 距离约束绑定到截面宽度参数
            pDistanceConstraintWidth->SetFamilyParameterDefinitionId(pRectWidthParamDef->GetElementId());

            // 柱两侧距离Y坐标轴等距
            Vector3d dimPositionEqual(0, sectionWidth / 2 + FamilyTemplateConst::CommonExtend, 0);
            IFamilyDistanceRatioConstraint* pEqualConstraint = CreateEqualConstraint(pDoc, profileLines[1], profileLines[3], pLeftRightCenterLocationLine
                , profileSketchPlane, dimPositionEqual);
        }
    }

    // 设置柱高度参数为驱动参数
    const IFamilyParameterDefinition* pHeightParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ColumnHeightBuiltInParameter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pHeightParamDef, L"柱高度参数不存在",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetFamilyParameterAsDrive(pHeightParamDef, true);
    // 获得柱高度参数的当前值
    double dColumnHeight = pFamilyManager->GetParameterValueAsDouble(pHeightParamDef);

    //创建斜拉伸体
    IFamilySlopedExtrusion* pSlopedExtrusion = IFamilySlopedExtrusion::Create(pDoc, coordProfile,
        profileSketch->GetOwnerElementId(), 0, 0, 0, dColumnHeight);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pSlopedExtrusion, L"pSlopedExtrusion为空!",L"GDMPLab",L"2024-03-30");

    // 绑定参数
    const IFamilyParameterDefinition* pAngleParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ColumnAngleBuiltInParameter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pAngleParamDef, L"倾斜角度参数不存在",L"GDMPLab",L"2024-03-30");
    //pFamilyManager->SetFamilyParameterAsDrive(pAngleParamDef, true);
    IElementParameterBindings *pParameterBinding = pSlopedExtrusion->GetOwnerElement()->GetElementParameters()->GetElementParameterBindings();
    pParameterBinding->AddParameterBinding(ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), SlopedExtrusionSectionAngleAroundProfileCoordXBuiltInParameter),
        ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), ColumnAngleBuiltInParameter), pFamilyManager->GetElementId(), false);

    const IFamilyParameterDefinition* pSectionAngleParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(SectionRotateAngleBuiltInParameter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pSectionAngleParamDef, L"倾斜角度参数不存在",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetFamilyParameterAsDrive(pSectionAngleParamDef, true);
    pParameterBinding = pSlopedExtrusion->GetOwnerElement()->GetElementParameters()->GetElementParameterBindings();
    pParameterBinding->AddParameterBinding(ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), SlopedExtrusionSectionAngleAroundProfileCoordZBuiltInParameter),
        ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), SectionRotateAngleBuiltInParameter), pFamilyManager->GetElementId(), false);

    // ExtrusionLength=高度/cos(倾斜角度)
    std::wstring formula = PARAMETER_DEF(ColumnHeightBuiltInParameter)->GetName() + L"/cos(" + PARAMETER_DEF(ColumnAngleBuiltInParameter)->GetName() + L")";

    IFamilyParameterDefinition* pExtrusionLength = IFamilyParameterDefinition::Create(pDoc, L"ExtrusionLength", FamilyParameterType::Length, true, formula);
    pExtrusionLength->SetUnitTypeId(UNIT(Length));
    pExtrusionLength->SetParameterTypeId(PARAMETER_TYPE(None));
    pFamilyManager->AddFamilyParameterDefinition(pExtrusionLength);

    pFamilyManager->SetParameterValueAsDouble(pExtrusionLength, dColumnHeight);

    pParameterBinding->AddParameterBinding(ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), ExtrusionEndOffsetBuiltInParameter),
        pFamilyManager->GetFamilyParameterDefinitionId(pExtrusionLength->GetElementId()), pFamilyManager->GetElementId(), false);

    // 退出草图编辑模式。
    IEditMode::Get(pDoc, L"SketchModeType")->EndEditing(pDoc);

    FamilySolverResult solveResult = FamilySolverUtils::SolveSketchOrDocument(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(solveResult == FamilySolverResult::Ok, L"约束解算失败" + StringUtil::ToWString((int)solveResult),L"GDMPLab",L"2024-03-30");
    pDoc->GetRegenerator()->RegenerateDocument();
}

void gcmp::FamStructureTemplateUtility::CreateCircleColumnBody(gcmp::IDocument *pDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    DefaultReferencePlanes refPlanes;
    DefaultReferencePlanesOptions refPlaneOptions = (DefaultReferencePlanesOptions)(TopBottomCenterReferencePlane
        | FrontBackCenterReferencePlane | LeftRightCenterReferencePlane);
    bool result = GetDefaultReferencePlanes(pDoc, refPlaneOptions, refPlanes);
    DBG_WARN_AND_RETURN_VOID_UNLESS(result, L"获取参照平面失败",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(refPlanes.m_pTopBottomCenter && refPlanes.m_pFrontBackCenter && refPlanes.m_pLeftRightCenter, L"参照平面获取失败！",L"GDMPLab",L"2024-03-30");

    // 轮廓草图，XOY面
    Coordinate3d coordProfile(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    IFamilySketchPlane* profileSketchPlane = IFamilySketchPlane::Create(pDoc, coordProfile);
    DBG_WARN_AND_RETURN_VOID_UNLESS(profileSketchPlane, L"轮廓草图平面创建失败！",L"GDMPLab",L"2024-03-30");
    IFamilySketch2D* profileSketch = IFamilySketch2D::Create(pDoc, profileSketchPlane->GetOwnerElementId());
    DBG_WARN_AND_RETURN_VOID_UNLESS(profileSketch, L"轮廓草图创建失败！",L"GDMPLab",L"2024-03-30");
    profileSketchPlane->SetSketchId(profileSketch->GetOwnerElementId());
    profileSketchPlane->SetReferencePlaneId(refPlanes.m_pTopBottomCenter->GetElementId());

    // 进入草图编辑模式
    IEditMode::Get(pDoc, L"SketchModeType")->StartEditing(pDoc, profileSketch->GetOwnerElementId(), true, false);

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 绘制轮廓线
    {
        const IFamilyParameterDefinition* pDiameterParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(CircSectionDiameterBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDiameterParameter, L"pDiameterParameter为空",L"GDMPLab",L"2024-03-30");
        double profileDiameter = pFamilyManager->GetParameterValueAsDouble(pDiameterParameter);

        // 绘制轮廓
        Vector3d centerPt(0.0, 0.0, 0.0);
        IFamily2DSketchArc* pArc1 = IFamily2DSketchArc::Create(pDoc, profileSketch->GetOwnerElementId(), profileSketchPlane->GetOwnerElementId()
            , centerPt, coordProfile.X(), coordProfile.Y(), profileDiameter / 2, -Constants::MATH_PI_2, Constants::MATH_PI_2, 1);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pArc1, L"pArc为空",L"GDMPLab",L"2024-03-30");
        // 创建直径约束
        Vector3d pos(0.0, 0.0, 0.0);
        IFamilyDiameterConstraint* pDiameterConstraint1 = IFamilyDiameterConstraint::Create(pDoc, pos, profileDiameter, pArc1->GetOwnerElementId()
            , profileSketch->GetOwnerElementId(), profileSketchPlane->GetOwnerElementId(), coordProfile);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDiameterConstraint1, L"pDiameterConstraint1为空",L"GDMPLab",L"2024-03-30");

        pDiameterConstraint1->SetFamilyParameterDefinitionId(pDiameterParameter->GetElementId());

        IFamily2DSketchArc* pArc2 = IFamily2DSketchArc::Create(pDoc, profileSketch->GetOwnerElementId(), profileSketchPlane->GetOwnerElementId()
            , centerPt, coordProfile.X(), coordProfile.Y(), profileDiameter / 2, Constants::MATH_PI_2, 3 * Constants::MATH_PI_2, 1);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pArc2, L"pArc2为空",L"GDMPLab",L"2024-03-30");
        // 创建直径约束
        IFamilyDiameterConstraint* pDiameterConstraint2 = IFamilyDiameterConstraint::Create(pDoc, pos, profileDiameter, pArc2->GetOwnerElementId()
            , profileSketch->GetOwnerElementId(), profileSketchPlane->GetOwnerElementId(), coordProfile);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDiameterConstraint2, L"pDiameterConstraint为空",L"GDMPLab",L"2024-03-30");

        pDiameterConstraint2->SetFamilyParameterDefinitionId(pDiameterParameter->GetElementId());
    }

    // 设置柱高度参数为驱动参数
    const IFamilyParameterDefinition* pHeightParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ColumnHeightBuiltInParameter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pHeightParamDef, L"柱高度参数不存在",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetFamilyParameterAsDrive(pHeightParamDef, true);
    // 获得柱高度参数的当前值
    double dColumnHeight = pFamilyManager->GetParameterValueAsDouble(pHeightParamDef);

    //创建斜拉伸体
    IFamilySlopedExtrusion* pSlopedExtrusion = IFamilySlopedExtrusion::Create(pDoc, coordProfile,
        profileSketch->GetOwnerElementId(), 0, 0, 0, dColumnHeight);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pSlopedExtrusion, L"pSlopedExtrusion为空!",L"GDMPLab",L"2024-03-30");

    // 绑定参数
    const IFamilyParameterDefinition* pAngleParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ColumnAngleBuiltInParameter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pAngleParamDef, L"倾斜角度参数不存在",L"GDMPLab",L"2024-03-30");
    IElementParameterBindings *pParameterBinding = pSlopedExtrusion->GetOwnerElement()->GetElementParameters()->GetElementParameterBindings();
    pParameterBinding->AddParameterBinding(ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), SlopedExtrusionSectionAngleAroundProfileCoordXBuiltInParameter),
        ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), ColumnAngleBuiltInParameter), pFamilyManager->GetElementId(), false);

    // ExtrusionLength=高度/cos(倾斜角度)
    std::wstring formula = PARAMETER_DEF(ColumnHeightBuiltInParameter)->GetName() + L"/cos(" + PARAMETER_DEF(ColumnAngleBuiltInParameter)->GetName() + L")";
    //const IFamilyParameterDefinition* pExtrusionLength = pFamilyManager->AddFamilyParameterDefinition(L"ExtrusionLength", FamilyParameterType::Length,
    //    ParameterStorageType::Double, UNIT(Length), PARAMETER_TYPE(None), true, true, formula);

    IFamilyParameterDefinition* pExtrusionLength = IFamilyParameterDefinition::Create(pDoc, L"ExtrusionLength", FamilyParameterType::Length, true, formula);
    pExtrusionLength->SetUnitTypeId(UNIT(Length));
    pExtrusionLength->SetParameterTypeId(PARAMETER_TYPE(None));
    pFamilyManager->AddFamilyParameterDefinition(pExtrusionLength);


    pFamilyManager->SetParameterValueAsDouble(pExtrusionLength, dColumnHeight);
    pParameterBinding->AddParameterBinding(ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), ExtrusionEndOffsetBuiltInParameter),
        pFamilyManager->GetFamilyParameterDefinitionId(pExtrusionLength->GetElementId()), pFamilyManager->GetElementId(), false);

    // 退出草图编辑模式。
    IEditMode::Get(pDoc, L"SketchModeType")->EndEditing(pDoc);

    FamilySolverResult solveResult = FamilySolverUtils::SolveSketchOrDocument(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(solveResult == FamilySolverResult::Ok, L"约束解算失败" + StringUtil::ToWString((int)solveResult),L"GDMPLab",L"2024-03-30");
    pDoc->GetRegenerator()->RegenerateDocument();
}

bool gcmp::FamStructureTemplateUtility::CreateDefaultReferencePlanes(gcmp::IDocument *pDbDoc
    , DefaultReferencePlanesOptions refPlaneOptions, const ReferencePlaneOffsets &refPlaneOffsets
    , DefaultReferencePlanes &refPlanes)
{
    if (refPlaneOptions & LeftReferencePlane)
    {
        Vector3d startPt(-refPlaneOffsets.m_leftOffset, -refPlaneOffsets.m_frontOffset, 0);
        Vector3d endPt(-refPlaneOffsets.m_leftOffset, refPlaneOffsets.m_backOffset, 0);
        gcmp::IReferencePlane *pLeft = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, startPt, endPt, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pLeft, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pLeft->GetBasicInformation()->SetName(FAMILY_LEFT_REFERENCE_PLANE_NAME);
        pLeft->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Left);
        double half = (refPlaneOffsets.m_frontOffset + refPlaneOffsets.m_backOffset) / 2.0;
        pLeft->SetVisibleUVMin(Vector2d(-half - FamilyTemplateConst::CommonExtend, -refPlaneOffsets.m_bottomOffset - FamilyTemplateConst::CommonExtend));
        pLeft->SetVisibleUVMax(Vector2d(half + FamilyTemplateConst::CommonExtend, refPlaneOffsets.m_topOffset + FamilyTemplateConst::CommonExtend));

        refPlanes.m_pLeft = pLeft;
    }

    if (refPlaneOptions & RightReferencePlane)
    {
        Vector3d startPt(refPlaneOffsets.m_rightOffset, -refPlaneOffsets.m_frontOffset, 0);
        Vector3d endPt(refPlaneOffsets.m_rightOffset, refPlaneOffsets.m_backOffset, 0);
        gcmp::IReferencePlane *pRight = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, startPt, endPt, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pRight, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pRight->GetBasicInformation()->SetName(FAMILY_RIGHT_REFERENCE_PLANE_NAME);
        pRight->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Right);
        double half = (refPlaneOffsets.m_frontOffset + refPlaneOffsets.m_backOffset) / 2.0;
        pRight->SetVisibleUVMin(Vector2d(-half - FamilyTemplateConst::CommonExtend, -refPlaneOffsets.m_bottomOffset - FamilyTemplateConst::CommonExtend));
        pRight->SetVisibleUVMax(Vector2d(half + FamilyTemplateConst::CommonExtend, refPlaneOffsets.m_topOffset + FamilyTemplateConst::CommonExtend));

        refPlanes.m_pRight = pRight;
    }

    if (refPlaneOptions & FrontReferencePlane)
    {
        Vector3d startPt(-refPlaneOffsets.m_leftOffset, -refPlaneOffsets.m_frontOffset, 0);
        Vector3d endPt(refPlaneOffsets.m_rightOffset, -refPlaneOffsets.m_frontOffset, 0);
        gcmp::IReferencePlane *pFront = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, startPt, endPt, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pFront, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pFront->GetBasicInformation()->SetName(FAMILY_FRONT_REFERENCE_PLANE_NAME);
        pFront->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Front);
        double half = (refPlaneOffsets.m_leftOffset + refPlaneOffsets.m_rightOffset) / 2.0;
        pFront->SetVisibleUVMin(Vector2d(-half - FamilyTemplateConst::CommonExtend, -refPlaneOffsets.m_bottomOffset - FamilyTemplateConst::CommonExtend));
        pFront->SetVisibleUVMax(Vector2d(half + FamilyTemplateConst::CommonExtend, refPlaneOffsets.m_topOffset + FamilyTemplateConst::CommonExtend));

        refPlanes.m_pFront = pFront;
    }

    if (refPlaneOptions & BackReferencePlane)
    {
        Vector3d startPt(-refPlaneOffsets.m_leftOffset, refPlaneOffsets.m_backOffset, 0);
        Vector3d endPt(refPlaneOffsets.m_rightOffset, refPlaneOffsets.m_backOffset, 0);
        gcmp::IReferencePlane *pBack = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, startPt, endPt, Vector3d::UnitZ);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pBack, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pBack->GetBasicInformation()->SetName(FAMILY_BACK_REFERENCE_PLANE_NAME);
        pBack->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Back);
        double half = (refPlaneOffsets.m_leftOffset + refPlaneOffsets.m_rightOffset) / 2.0;
        pBack->SetVisibleUVMin(Vector2d(-half - FamilyTemplateConst::CommonExtend, -refPlaneOffsets.m_bottomOffset - FamilyTemplateConst::CommonExtend));
        pBack->SetVisibleUVMax(Vector2d(half + FamilyTemplateConst::CommonExtend, refPlaneOffsets.m_topOffset + FamilyTemplateConst::CommonExtend));

        refPlanes.m_pBack = pBack;
    }

    if (refPlaneOptions & TopReferencePlane)
    {
        Vector3d startPt(-refPlaneOffsets.m_leftOffset, 0, refPlaneOffsets.m_topOffset);
        Vector3d endPt(refPlaneOffsets.m_rightOffset, 0, refPlaneOffsets.m_topOffset);
        gcmp::IReferencePlane *pTop = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, startPt, endPt, Vector3d::UnitY);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pTop, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pTop->GetBasicInformation()->SetName(FAMILY_TOP_REFERENCE_PLANE_NAME);
        pTop->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Top);
        double half = (refPlaneOffsets.m_leftOffset + refPlaneOffsets.m_rightOffset) / 2.0;
        pTop->SetVisibleUVMin(Vector2d(-half - FamilyTemplateConst::CommonExtend, -refPlaneOffsets.m_frontOffset - FamilyTemplateConst::CommonExtend));
        pTop->SetVisibleUVMax(Vector2d(half + FamilyTemplateConst::CommonExtend, refPlaneOffsets.m_backOffset + FamilyTemplateConst::CommonExtend));

        refPlanes.m_pTop = pTop;
    }

    if (refPlaneOptions & BottomReferencePlane)
    {
        Vector3d startPt(-refPlaneOffsets.m_leftOffset, 0, -refPlaneOffsets.m_bottomOffset);
        Vector3d endPt(refPlaneOffsets.m_rightOffset, 0, -refPlaneOffsets.m_bottomOffset);
        gcmp::IReferencePlane *pBottom = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, startPt, endPt, Vector3d::UnitY);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pBottom, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pBottom->GetBasicInformation()->SetName(FAMILY_BOTTOM_REFERENCE_PLANE_NAME);
        pBottom->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Bottom);
        double half = (refPlaneOffsets.m_leftOffset + refPlaneOffsets.m_rightOffset) / 2.0;
        pBottom->SetVisibleUVMin(Vector2d(-half - FamilyTemplateConst::CommonExtend, -refPlaneOffsets.m_frontOffset - FamilyTemplateConst::CommonExtend));
        pBottom->SetVisibleUVMax(Vector2d(half + FamilyTemplateConst::CommonExtend, refPlaneOffsets.m_backOffset + FamilyTemplateConst::CommonExtend));

        refPlanes.m_pBottom = pBottom;
    }

    return true;
}

bool gcmp::FamStructureTemplateUtility::GetDefaultReferencePlanes(gcmp::IDocument *pDbDoc, DefaultReferencePlanesOptions refPlaneOptions, DefaultReferencePlanes &refPlanes)
{
    std::vector<IReferencePlane*> allRefPlanes = IReferencePlane::GetAllReferencePlanes(pDbDoc);
    FOR_EACH(pRefPlane, allRefPlanes)
    {
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pRefPlane != nullptr, L"pRefPlane为空",L"GDMPLab",L"2024-03-30");

        if ((refPlaneOptions & LeftReferencePlane) && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::Left)
        {
            refPlanes.m_pLeft = pRefPlane;
        }
        if ((refPlaneOptions & RightReferencePlane) && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::Right)
        {
            refPlanes.m_pRight = pRefPlane;
        }
        if ((refPlaneOptions & FrontReferencePlane) && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::Front)
        {
            refPlanes.m_pFront = pRefPlane;
        }
        if ((refPlaneOptions & BackReferencePlane) && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::Back)
        {
            refPlanes.m_pBack = pRefPlane;
        }
        if ((refPlaneOptions & TopReferencePlane) && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::Top)
        {
            refPlanes.m_pTop = pRefPlane;
        }
        if ((refPlaneOptions & BottomReferencePlane) && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::Bottom)
        {
            refPlanes.m_pBottom = pRefPlane;
        }
        if ((refPlaneOptions & LeftRightCenterReferencePlane) && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight)
        {
            refPlanes.m_pLeftRightCenter = pRefPlane;
        }
        if ((refPlaneOptions & FrontBackCenterReferencePlane) && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack)
        {
            refPlanes.m_pFrontBackCenter = pRefPlane;
        }
        if ((refPlaneOptions & TopBottomCenterReferencePlane) && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfTopBottom)
        {
            refPlanes.m_pTopBottomCenter = pRefPlane;
        }
    }

    return true;
}

gfam::IFamilyDistanceConstraint *gcmp::FamStructureTemplateUtility::CreateDistanceConstraint(gcmp::IDocument *pDbDoc
    , IReferencePlane *pFirstRefPlane, IReferencePlane *pSecondRefPlane
    , const Coordinate3d &coord, const Vector3d &dimPosition)
{
    gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
    gfam::IFamilyDistanceConstraint* pDistanceConstraint = CreateDistanceConstraint(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, coord
        , pFirstRefPlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
        , pSecondRefPlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
    pDistanceConstraint->CalcDimValue();

    return pDistanceConstraint;
}

gfam::IFamilyAngleConstraint* gcmp::FamStructureTemplateUtility::CreateAngleConstraint(gcmp::IDocument* pDoc, const gcmp::Coordinate3d& coord, gcmp::IElement* pEle1, gcmp::GraphicsNodeReferenceType refType1, const gcmp::GraphicsNodeId& leafTag1, gcmp::IElement* pEle2, gcmp::GraphicsNodeReferenceType refType2, const gcmp::GraphicsNodeId& leafTag2)
{
    DBG_WARN_AND_RETURN_UNLESS(nullptr != pDoc, nullptr, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyAngleConstraint* pAngleConstraint = IFamilyAngleConstraint::Create(pDoc, ElementId(), ElementId(), coord);
    DBG_WARN_AND_RETURN_UNLESS(nullptr != pAngleConstraint, nullptr, L"无法创建pAngleConstraint",L"GDMPLab",L"2024-03-30");
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pEle1->GetElementId(), leafTag1, refType1);
    pAngleConstraint->AddReferenceObject(TransferOwnership(opRef1));

    gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pEle2->GetElementId(), leafTag2, refType2);
    pAngleConstraint->AddReferenceObject(TransferOwnership(opRef2));

    return pAngleConstraint;
}

gfam::IFamilyDistanceConstraint *gcmp::FamStructureTemplateUtility::CreateDistanceConstraint(gcmp::IDocument *pDbDoc
    , const gfam::IFamily2DSketchLine *pFirstLine, const gfam::IFamily2DSketchLine *pSecondLine
    , const IFamilySketchPlane* pSketchPlane, const Vector3d &dimPosition)
{
    DBG_WARN_AND_RETURN_UNLESS(pDbDoc, nullptr, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    IFamilyMultiDistanceDimension*pDim = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPosition, FamilyTemplateConst::DimScale
        , pSketchPlane->GetOwnerElementId(), pSketchPlane->GetSketchId(), pSketchPlane->GetPlane(), false);
    DBG_WARN_AND_RETURN_UNLESS(nullptr != pDim, nullptr, L"无法创建FamilyMultiDistanceDimension",L"GDMPLab",L"2024-03-30");
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pFirstLine->GetOwnerElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
    pDim->AddReferenceObject(TransferOwnership(opRef1));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pSecondLine->GetOwnerElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
    pDim->AddReferenceObject(TransferOwnership(opRef2));

    IFamilyDistanceConstraint*pDistanceConstraint = IFamilyDistanceConstraint::Create(pDbDoc
        , pSketchPlane->GetSketchId(), pSketchPlane->GetOwnerElementId(), pDim->GetOwnerElementId(), pSketchPlane->GetPlane());
    DBG_WARN_AND_RETURN_UNLESS(nullptr != pDistanceConstraint, nullptr, L"无法创建FamilyDistanceConstraint",L"GDMPLab",L"2024-03-30");
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pFirstLine->GetOwnerElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
    pDistanceConstraint->AddReferenceObject(TransferOwnership(opRef3));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef4 = IGraphicsNodeReference::Create(pSecondLine->GetOwnerElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
    pDistanceConstraint->AddReferenceObject(TransferOwnership(opRef4));
    pDim->AddConstraintObject(pDistanceConstraint->GetOwnerElementId());
    pDistanceConstraint->CalcDimValue();

    return pDistanceConstraint;
}

IFamilyDistanceRatioConstraint *gcmp::FamStructureTemplateUtility::CreateEqualConstraint(gcmp::IDocument *pDbDoc
    , IReferencePlane *pFirstRefPlane, IReferencePlane *pSecondRefPlane, IReferencePlane *pMidRefPlane
    , const Coordinate3d &coord, const Vector3d &dimPosition)
{
    IFamilyMultiDistanceDimension*pDimEqual = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPosition, FamilyTemplateConst::DimScale, ElementId(), ElementId(), coord, true);
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pFirstRefPlane->GetElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pMidRefPlane->GetElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pSecondRefPlane->GetElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

    IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDbDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), coord);
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pFirstRefPlane->GetElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pMidRefPlane->GetElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pSecondRefPlane->GetElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
    pEqualConstraint->SetRatioValue(0.5);

    pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
    return pEqualConstraint;
}

gfam::IFamilyDistanceRatioConstraint *gcmp::FamStructureTemplateUtility::CreateEqualConstraint(gcmp::IDocument *pDbDoc
    , gfam::IFamily2DSketchLine *pFirstLine, gfam::IFamily2DSketchLine * pSecondLine, gfam::IFamily2DSketchLine *pMidLine
    , IFamilySketchPlane* pSketchPlane, const Vector3d &dimPosition)
{
    IFamilyMultiDistanceDimension*pDimEqual = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPosition, FamilyTemplateConst::DimScale
        , pSketchPlane->GetOwnerElementId(), pSketchPlane->GetSketchId(), pSketchPlane->GetPlane(), true);
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pFirstLine->GetOwnerElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pMidLine->GetOwnerElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pSecondLine->GetOwnerElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

    IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDbDoc
        , pSketchPlane->GetSketchId(), pSketchPlane->GetOwnerElementId(), pDimEqual->GetOwnerElementId(), pSketchPlane->GetPlane());
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pFirstLine->GetOwnerElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pMidLine->GetOwnerElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pSecondLine->GetOwnerElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
    pEqualConstraint->SetRatioValue(0.5);

    pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
    return pEqualConstraint;
}

gfam::IFamilyDistanceRatioConstraint *gcmp::FamStructureTemplateUtility::CreateEqualConstraint(gcmp::IDocument* pDbDoc
    , const gfam::IFamily2DSketchLine *pFirstLine, const gfam::IFamily2DSketchLine *pSecondLine, const IReferencePlane *pMidRefPlane
    , const gfam::IFamilySketchPlane* pSketchPlane, const Vector3d &dimPosition)
{
    IFamilyMultiDistanceDimension*pDimEqual = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPosition, FamilyTemplateConst::DimScale
        , pSketchPlane->GetOwnerElementId(), pSketchPlane->GetSketchId(), pSketchPlane->GetPlane(), true);
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pFirstLine->GetOwnerElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pMidRefPlane->GetElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pSecondLine->GetOwnerElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

    IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDbDoc
        , pSketchPlane->GetSketchId(), pSketchPlane->GetOwnerElementId(), pDimEqual->GetOwnerElementId(), pSketchPlane->GetPlane());
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pFirstLine->GetOwnerElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pMidRefPlane->GetElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pSecondLine->GetOwnerElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
    pEqualConstraint->SetRatioValue(0.5);

    pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
    return pEqualConstraint;
}

gfam::IFamilyGeometryConstraint *gcmp::FamStructureTemplateUtility::CreateAlignConstraint(gcmp::IDocument *pDbDoc
    , IReferencePlane *pRefPlane, IFamily2DSketchLine *pSketchLine, IFamilySketchPlane* pSketchPlane)
{
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pRefPlane->GetElementId(), GraphicsNodeId(1));
    OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pSketchLine->GetOwnerElementId(), GraphicsNodeId(1));
    return quick_cast<IFamilyGeometryConstraint>( FamilyConstraintUtils::AddGeometryConstraint(pDbDoc, FamilyConstraintType::AlignGeometry, *opRef1, *opRef2, pSketchPlane->GetOwnerElementId(),
        pSketchPlane->GetSketchId(), pSketchPlane->GetPlane()));
}

bool gcmp::FamStructureTemplateUtility::CreateStartEndPtAlignConstraints(gcmp::IDocument *pDbDoc
    , IReferencePlane *pStartRefPlane, IReferencePlane *pEndRefPlane
    , gfam::IFamily2DSketchLine *pSketchLine, gfam::IFamilySketchPlane *pSketchPlane)
{
    OwnerPtr<IGraphicsNodeReference> gNodeRef1 = IGraphicsNodeReference::Create(pSketchLine->GetOwnerElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::StartPoint);
    OwnerPtr<IGraphicsNodeReference> gNodeRef2 = IGraphicsNodeReference::Create(pSketchLine->GetOwnerElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::EndPoint);
    OwnerPtr<IGraphicsNodeReference> refLeftPlane = IGraphicsNodeReference::Create(pStartRefPlane->GetElementId(), (GraphicsNodeId)1, GraphicsNodeReferenceType::GraphicsNodeSelf);
    OwnerPtr<IGraphicsNodeReference> refRightPlane = IGraphicsNodeReference::Create(pEndRefPlane->GetElementId(), (GraphicsNodeId)1, GraphicsNodeReferenceType::GraphicsNodeSelf);
    IFamilyGeometryConstraint *pStartConstraint = FamilyConstraintUtils::AddGeometryConstraint(pDbDoc, FamilyConstraintType::AlignGeometry, *refLeftPlane, *gNodeRef1, pSketchPlane->GetOwnerElementId(), pSketchPlane->GetSketchId());
    IFamilyGeometryConstraint *pEndConstraint = FamilyConstraintUtils::AddGeometryConstraint(pDbDoc, FamilyConstraintType::AlignGeometry, *refRightPlane, *gNodeRef2, pSketchPlane->GetOwnerElementId(), pSketchPlane->GetSketchId());

    return pStartConstraint && pEndConstraint;
}

//////////////////////////////////////////////////////////////////////////
bool FamStructureTemplateUtility::InitRectBeamFamilyDocument(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    bool bOk = FamStructureTemplateDocument::InitBeamTemplateFamilyDocument(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"InitBeamTemplateFamilyDocument失败",L"GDMPLab",L"2024-03-30");

    // 外面Id参数
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create(RectBasicBeamExteriorFaceNodeTag), PARAMETER_UID(ExteriorFaceNodeTagBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");
    // 内面Id参数
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create(RectBasicBeamInteriorFaceNodeTag), PARAMETER_UID(InteriorFaceNodeTagBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 设置梁的截面形状
    const IFamilyParameterDefinition* pSectionShapeTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(SectionShapeBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSectionShapeTypeDef, L"pSectionShapeTypeDef为空",L"GDMPLab",L"2024-03-30");
    StructureInstanceSectionShapeType sectionType = StructureInstanceSectionShapeType::SECTION_SHAPE_RECTANGLE;
    pFamilyManager->SetParameterValueStorage(pSectionShapeTypeDef, IParameterValueInt::Create((int)sectionType));

    // 给当前类型命名
    pFamilyManager->RenameCurrentFamilyType(DEFAULT_RECT_BEAM_300_600);
    return true;
}

bool FamStructureTemplateUtility::AddRectBeamType(IFamilyManager* pFamilyManager, const std::wstring& familyType, double profileWidth, double profileHeight)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    pFamilyManager->AddFamilyType(familyType);
    pFamilyManager->SetCurrentFamilyType(familyType);

    const IFamilyParameterDefinition* pPDColumnProfileWidth = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionWidthBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPDColumnProfileWidth != nullptr, L"无法获得截面宽度参数",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pPDColumnProfileWidth, profileWidth);

    const IFamilyParameterDefinition* pPDColumnProfileHeight = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPDColumnProfileHeight != nullptr, L"无法获得截面高度参数",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pPDColumnProfileHeight, profileHeight);

    return true;
}

bool FamStructureTemplateUtility::CreateRectBeamBody(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilySketch2D* pPathSketch = CreateRectBeamPathSketch(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPathSketch, L"pPathSketch为空",L"GDMPLab",L"2024-03-30");
    pPathSketch->SetChildVisible(false);

    IFamilySketch2D* pProfileSketch = CreateRectBeamProfileSketch(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pProfileSketch, L"pProfileSketch为空",L"GDMPLab",L"2024-03-30");
    pProfileSketch->SetChildVisible(false);

    IFamilySweep* pBody = IFamilySweep::Create(pDoc, pPathSketch->GetOwnerElementId(), pProfileSketch->GetOwnerElementId(), 0);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pBody, L"pBody为空",L"GDMPLab",L"2024-03-30");

    bool bOk = pDoc->GetRegenerator()->RegenerateDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"族文档生成失败",L"GDMPLab",L"2024-03-30");

    return true;
}

IFamilySketch2D* FamStructureTemplateUtility::CreateRectBeamProfileSketch(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 创建草图平面，用于绘制横截面草图
    Coordinate3d baseCoord(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);
    IFamilySketchPlane* pBaseSketchPlane = IFamilySketchPlane::Create(pDoc, baseCoord);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBaseSketchPlane, L"pBaseSketchPlane为空",L"GDMPLab",L"2024-03-30");
    ElementId baseSketchPlaneId = pBaseSketchPlane->GetOwnerElementId();
    IFamilySketch2D* pBaseSketch = IFamilySketch2D::Create(pDoc, baseSketchPlaneId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBaseSketch, L"pBaseSketch为空",L"GDMPLab",L"2024-03-30");
    ElementId baseSketchId = pBaseSketch->GetOwnerElementId();
    pBaseSketchPlane->SetSketchId(baseSketchId);

    // 绘制轮廓
    double profileWidth = 300;
    double profileHeight = 600;
    IFamily2DSketchLine* pLine[4] = { nullptr, nullptr, nullptr, nullptr }; // 顺时针， 0：矩形顶边
    {
        Vector3d vts[4];
        vts[0] = Vector3d(0, -profileWidth / 2, 0);
        vts[1] = Vector3d(0, profileWidth / 2, 0);
        vts[2] = Vector3d(0, profileWidth / 2, -profileHeight);
        vts[3] = Vector3d(0, -profileWidth / 2, -profileHeight);
        bool bOk = CreateRectangle(pDoc, pBaseSketchPlane, pBaseSketch, vts, pLine);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"CreateRectangle失败",L"GDMPLab",L"2024-03-30");
    }

    {
        // 竖直草图线和前后参考面对齐
        std::vector<IReferencePlane*> allRefPlanes = IReferencePlane::GetAllReferencePlanes(pDoc);
        IReferencePlane * pReferencePlaneFront = GetReferencePlane(allRefPlanes, FAMILY_FRONT_REFERENCE_PLANE_NAME);
        IReferencePlane * pReferencePlaneBack = GetReferencePlane(allRefPlanes, FAMILY_BACK_REFERENCE_PLANE_NAME);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pReferencePlaneFront && pReferencePlaneBack, L"参照平面获取失败！",L"GDMPLab",L"2024-03-30");

        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::AlignGeometry, pReferencePlaneFront->GetElementId(), FamilyConstraintReferenceType::Self, pLine[3]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pBaseSketchPlane, pBaseSketch);
        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::AlignGeometry, pReferencePlaneBack->GetElementId(), FamilyConstraintReferenceType::Self, pLine[1]->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pBaseSketchPlane, pBaseSketch);
    }

    {
        // 高度约束
        Vector3d dimPos(0, profileWidth, 0);
        IFamilyDistanceConstraint* pHeightConstraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, baseSketchId, baseSketchPlaneId, baseCoord,
            pLine[0]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pLine[2]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pHeightConstraint->CalcDimValue();

        const IFamilyParameterDefinition* pHeightParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pHeightParameter, L"pHeightParameter为空",L"GDMPLab",L"2024-03-30");
        pHeightConstraint->SetFamilyParameterDefinitionId(pHeightParameter->GetElementId());
    }
    {
        // 矩形底边和Y轴的距离约束
        // 注意草图线不要和参照平面加距离约束，而要和草图内的坐标轴加距离约束。
        // 因为草图可能倾斜，此时参照平面不再垂直于草图平面。
        Vector3d bottomOffsetPos(0, profileWidth, profileHeight);
        IFamilyDistanceConstraint* pBottomOffsetConstraint = AddDistanceConstraint(pDoc, bottomOffsetPos, FamilyTemplateConst::DimScale, baseSketchId, baseSketchPlaneId, baseCoord,
            pBaseSketchPlane->GetOwnerElement(), GraphicsNodeId(0), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pLine[2]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pBottomOffsetConstraint->CalcDimValue();

        const IFamilyParameterDefinition* pBotomOffsetParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(BeamBottomOffsetBuiltInParameter));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBotomOffsetParameter, L"pBotomOffsetParameter为空",L"GDMPLab",L"2024-03-30");
        pBottomOffsetConstraint->SetFamilyParameterDefinitionId(pBotomOffsetParameter->GetElementId());
    }

    return pBaseSketch;
}

IFamilySketch2D* FamStructureTemplateUtility::CreateRectBeamPathSketch(IDocument* pDoc)
{
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 创建平面草图
    Coordinate3d coord(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    IFamilySketchPlane* pSketchPlane = IFamilySketchPlane::Create(pDoc, coord);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSketchPlane, L"pSketchPlane为空",L"GDMPLab",L"2024-03-30");
    ElementId sketchPlaneId = pSketchPlane->GetOwnerElementId();
    IFamilySketch2D* pSketch = IFamilySketch2D::Create(pDoc, sketchPlaneId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSketch, L"pSketch为空",L"GDMPLab",L"2024-03-30");
    ElementId sketchId = pSketch->GetOwnerElementId();
    pSketchPlane->SetSketchId(sketchId);

    // 绘制路径
    IFamily2DSketchLine* pPathLine = IFamily2DSketchLine::Create(pDoc, sketchId, sketchPlaneId, Vector3d::Zero, Vector3d(4000, 0, 0));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPathLine, L"pPathLine为空",L"GDMPLab",L"2024-03-30");

    // 路径约束
    std::vector<IReferencePlane*> allRefPlanes = IReferencePlane::GetAllReferencePlanes(pDoc);
    IReferencePlane* pReferencePlaneLeft = GetReferencePlane(allRefPlanes, FAMILY_LEFT_RIGHT_CENTER_REFERENCE_PLANE_NAME);
    IReferencePlane* pReferencePlaneRight = GetReferencePlane(allRefPlanes, FAMILY_RIGHT_REFERENCE_PLANE_NAME);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pReferencePlaneLeft && pReferencePlaneRight, L"参照平面获取失败！",L"GDMPLab",L"2024-03-30");

    FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::AlignGeometry, pReferencePlaneLeft->GetElementId(), FamilyConstraintReferenceType::Self, pPathLine->GetOwnerElementId(), FamilyConstraintReferenceType::Start, pSketchPlane, pSketch);
    FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::AlignGeometry, pReferencePlaneRight->GetElementId(), FamilyConstraintReferenceType::Self, pPathLine->GetOwnerElementId(), FamilyConstraintReferenceType::End, pSketchPlane, pSketch);

    return pSketch;
}

//////////////////////////////////////////////////////////////////////////
bool FamStructureTemplateUtility::InitVariableSectionRectBeamFamilyDocument(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 结构类型参数
    bool bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)StructureType::CastInPlaceConcrete), PARAMETER_UID(StructureTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 梁类型参数
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)StructureBeamType::VariableSection), PARAMETER_UID(CategorySubTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 梁的截面形状
    StructureInstanceSectionShapeType sectionType = StructureInstanceSectionShapeType::SECTION_SHAPE_RECTANGLE;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)sectionType), PARAMETER_UID(SectionShapeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建梁模板截面类型参数失败",L"GDMPLab",L"2024-03-30");

    // 外面Id参数
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create(RectVariableSectionBeamExteriorFaceNodeTag), PARAMETER_UID(ExteriorFaceNodeTagBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");
    // 内面Id参数
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create(RectVariableSectionBeamInteriorFaceNodeTag), PARAMETER_UID(InteriorFaceNodeTagBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 截面宽度参数
    double profileWidth = 500;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(profileWidth), PARAMETER_UID(RectSectionWidthBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"AddBuiltInParameterDefination失败",L"GDMPLab",L"2024-03-30");

    // 起点截面高度参数
    double startProfileHeight = 250;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(startProfileHeight), PARAMETER_UID(RectSectionStartHeightBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"AddBuiltInParameterDefination失败",L"GDMPLab",L"2024-03-30");

    // 终点截面高度参数
    double endProfileHeight = 900;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(endProfileHeight), PARAMETER_UID(RectSectionEndHeightBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"AddBuiltInParameterDefination失败",L"GDMPLab",L"2024-03-30");

    // 放置类型，以便族服务更新扫掠体路径
    const IFamilyParameterDefinition* pPlacementTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPlacementTypeDef, L"pPlacementTypeDef为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPlacementTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnLevel));

    // 给当前类型命名
    pFamilyManager->RenameCurrentFamilyType(DEFAULT_VARIABLE_SECTION_RECT_BEAM_250_900_500mm);
    return true;
}

bool FamStructureTemplateUtility::AddVariableSectionRectBeamType(IFamilyManager* pFamilyManager, const std::wstring& familyType, double profileStartHeight, double profileEndHeight, double profileWidth)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    pFamilyManager->AddFamilyType(familyType);
    pFamilyManager->SetCurrentFamilyType(familyType);

    const IFamilyParameterDefinition* pPDColumnProfileWidth = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionWidthBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPDColumnProfileWidth, L"无法获得截面宽度参数",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pPDColumnProfileWidth, profileWidth);

    const IFamilyParameterDefinition* pPDColumnProfileStartHeight = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionStartHeightBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPDColumnProfileStartHeight, L"无法获得截面起点高度参数",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pPDColumnProfileStartHeight, profileStartHeight);

    const IFamilyParameterDefinition* pPDColumnProfileEndHeight = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionEndHeightBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPDColumnProfileEndHeight, L"无法获得截面终点高度参数",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pPDColumnProfileEndHeight, profileEndHeight);

    return true;
}

bool FamStructureTemplateUtility::CreateVariableSectionRectBeamBody(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilySketch2D* pStartProfileSketch = CreateVariableSectionRectBeamProfileSketch(pDoc, PARAMETER_UID(RectSectionWidthBuiltInParameter), PARAMETER_UID(RectSectionStartHeightBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pStartProfileSketch, L"pStartProfileSketch为空",L"GDMPLab",L"2024-03-30");
    pStartProfileSketch->SetChildVisible(false);

    IFamilySketch2D* pEndProfileSketch = CreateVariableSectionRectBeamProfileSketch(pDoc, PARAMETER_UID(RectSectionWidthBuiltInParameter), PARAMETER_UID(RectSectionEndHeightBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pEndProfileSketch, L"pEndProfileSketch为空",L"GDMPLab",L"2024-03-30");
    pEndProfileSketch->SetChildVisible(false);

    IFamilySketch2D* pPathSketch = CreateVariableSectionRectBeamPathSketch(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPathSketch, L"pPathSketch为空",L"GDMPLab",L"2024-03-30");
    pPathSketch->SetChildVisible(false);

    IFamilySweptLoft* pBody = IFamilySweptLoft::Create(pDoc, pStartProfileSketch->GetOwnerElementId(), pEndProfileSketch->GetOwnerElementId(), pPathSketch->GetOwnerElementId());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pBody, L"无法创建放样融合体",L"GDMPLab",L"2024-03-30");

    bool bOk = pDoc->GetRegenerator()->RegenerateDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"族文档生成失败",L"GDMPLab",L"2024-03-30");

    return true;
}

IFamilySketch2D* FamStructureTemplateUtility::CreateVariableSectionRectBeamProfileSketch(IDocument* pDoc, const UniIdentity& widthParamUid, const UniIdentity& heightParamUid)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 创建草图平面，用于绘制横截面草图
    Coordinate3d baseCoord(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);
    IFamilySketchPlane* pBaseSketchPlane = IFamilySketchPlane::Create(pDoc, baseCoord);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBaseSketchPlane, L"pBaseSketchPlane为空",L"GDMPLab",L"2024-03-30");
    ElementId baseSketchPlaneId = pBaseSketchPlane->GetOwnerElementId();
    IFamilySketch2D* pBaseSketch = IFamilySketch2D::Create(pDoc, baseSketchPlaneId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBaseSketch, L"pBaseSketch为空",L"GDMPLab",L"2024-03-30");
    ElementId baseSketchId = pBaseSketch->GetOwnerElementId();
    pBaseSketchPlane->SetSketchId(baseSketchId);

    // 绘制轮廓
    double profileWidth = 500;
    double profileHeight = 250;
    IFamily2DSketchLine* pLine[4] = { nullptr, nullptr, nullptr, nullptr }; // 顺时针， 0：矩形顶边
    {
        Vector3d vts[4];
        vts[0] = Vector3d(0, -profileWidth / 2, 0);
        vts[1] = Vector3d(0, profileWidth / 2, 0);
        vts[2] = Vector3d(0, profileWidth / 2, -profileHeight);
        vts[3] = Vector3d(0, -profileWidth / 2, -profileHeight);
        bool bOk = CreateRectangle(pDoc, pBaseSketchPlane, pBaseSketch, vts, pLine);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"CreateRectangle失败",L"GDMPLab",L"2024-03-30");
    }

    {
        // 宽度约束
        Vector3d dimPos(0, 0, profileHeight);
        IFamilyDistanceConstraint* pWidthConstraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, baseSketchId, baseSketchPlaneId, baseCoord,
            pLine[3]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pLine[1]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pWidthConstraint->CalcDimValue();

        const IFamilyParameterDefinition* pWidthParameter = pFamilyManager->GetFamilyParameterDefinition(widthParamUid);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pWidthParameter, L"pWidthParameter为空",L"GDMPLab",L"2024-03-30");
        pWidthConstraint->SetFamilyParameterDefinitionId(pWidthParameter->GetElementId());
    }
    {
        // 高度约束
        Vector3d dimPos(0, profileWidth, 0);
        IFamilyDistanceConstraint* pHeightConstraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, baseSketchId, baseSketchPlaneId, baseCoord,
            pLine[0]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pLine[2]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pHeightConstraint->CalcDimValue();

        const IFamilyParameterDefinition* pHeightParameter = pFamilyManager->GetFamilyParameterDefinition(heightParamUid);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pHeightParameter, L"pHeightParameter为空",L"GDMPLab",L"2024-03-30");
        pHeightConstraint->SetFamilyParameterDefinitionId(pHeightParameter->GetElementId());
    }
    {
        // 取出内置参照平面
        std::vector<IReferencePlane*> referencePlanes;
        ReferencePlaneUtils::GetVisibleReferencePlanes(pDoc, baseCoord, referencePlanes);
        IReferencePlane* pFrontBackCenterPlane = GetReferencePlane(referencePlanes, FAMILY_FRONT_BACK_CENTER_REFERENCE_PLANE_NAME);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFrontBackCenterPlane, L"pFrontBackCenterPlane为空",L"GDMPLab",L"2024-03-30");

        // 矩形左右边和Z轴的均分约束
        Vector3d frontBackDimPos(0, 0, profileHeight + FamilyTemplateConst::CommonExtend);
        AddEqualDistanceConstraint(pDoc, frontBackDimPos, FamilyTemplateConst::DimScale, baseSketchId, baseSketchPlaneId, baseCoord, pLine[3]->GetOwnerElement(), GraphicsNodeId(1), pBaseSketchPlane->GetOwnerElement(), GraphicsNodeId(1), pLine[1]->GetOwnerElement(), GraphicsNodeId(1));

        // 矩形顶边和Y轴对齐
        OwnerPtr<IGraphicsNodeReference> ref1 = IGraphicsNodeReference::Create(baseSketchPlaneId, GraphicsNodeId(0));
        OwnerPtr<IGraphicsNodeReference> ref2 = IGraphicsNodeReference::Create(pLine[0]->GetOwnerElementId(), GraphicsNodeId(1));
        FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry, *ref1, *ref2, baseSketchPlaneId, baseSketchId, baseCoord);
    }

    return pBaseSketch;
}

IFamilySketch2D* FamStructureTemplateUtility::CreateVariableSectionRectBeamPathSketch(IDocument* pDoc)
{
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 创建平面草图
    Coordinate3d coord(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    IFamilySketchPlane* pSketchPlane = IFamilySketchPlane::Create(pDoc, coord);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSketchPlane, L"pSketchPlane为空",L"GDMPLab",L"2024-03-30");
    ElementId sketchPlaneId = pSketchPlane->GetOwnerElementId();
    IFamilySketch2D* pSketch = IFamilySketch2D::Create(pDoc, sketchPlaneId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSketch, L"pSketch为空",L"GDMPLab",L"2024-03-30");
    ElementId sketchId = pSketch->GetOwnerElementId();
    pSketchPlane->SetSketchId(sketchId);

    // 绘制路径
    IFamily2DSketchLine* pBodyLine = IFamily2DSketchLine::Create(pDoc, sketchId, sketchPlaneId, Vector3d::Zero, Vector3d(3000, 0, 0));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBodyLine, L"pBodyLine为空",L"GDMPLab",L"2024-03-30");

    // 取出内置参照平面
    std::vector<IReferencePlane *> referencePlanes;
    ReferencePlaneUtils::GetVisibleReferencePlanes(pDoc, coord, referencePlanes);
    IReferencePlane * pLeftRightCenterPlane = GetReferencePlane(referencePlanes, FAMILY_LEFT_RIGHT_CENTER_REFERENCE_PLANE_NAME);
    IReferencePlane * pFrontBackCenterPlane = GetReferencePlane(referencePlanes, FAMILY_FRONT_BACK_CENTER_REFERENCE_PLANE_NAME);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pLeftRightCenterPlane && pFrontBackCenterPlane, L"pLeftRightCenterPlane && pFrontBackCenterPlane为空",L"GDMPLab",L"2024-03-30");

    // X轴对齐约束
    FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::AlignGeometry, pBodyLine->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pFrontBackCenterPlane->GetElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);

    // Y轴对齐约束
    FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::AlignGeometry, pBodyLine->GetOwnerElementId(), FamilyConstraintReferenceType::Start, pLeftRightCenterPlane->GetElementId(), FamilyConstraintReferenceType::Self, pSketchPlane, pSketch);

    return pSketch;
}

//////////////////////////////////////////////////////////////////////////
bool FamStructureTemplateUtility::InitCustomizedProfileBeamFamilyDocument(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 结构类型参数
    bool bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)StructureType::CastInPlaceConcrete), PARAMETER_UID(StructureTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建结构类型参数失败",L"GDMPLab",L"2024-03-30");

    // 梁类型参数
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)StructureBeamType::CustomizedProfile), PARAMETER_UID(CategorySubTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建梁类型参数参数失败",L"GDMPLab",L"2024-03-30");

    // 梁的截面形状
    StructureInstanceSectionShapeType sectionType = StructureInstanceSectionShapeType::SECTION_SHAPE_CUSTOMIZED;
    bOk = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)sectionType), PARAMETER_UID(SectionShapeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建梁模板截面类型参数失败",L"GDMPLab",L"2024-03-30");

    // 设置放置类型
    const IFamilyParameterDefinition* pPlacementTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPlacementTypeDef, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPlacementTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnLevel));

    // 给当前类型命名
    pFamilyManager->RenameCurrentFamilyType(DEFAULT_CUSTOMIZED_PROFILE);

    return true;
}

bool FamStructureTemplateUtility::CreateCustomizedProfileBeamBody(IDocument* pDoc, const IPolyCurve* pLoop)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    // 扫掠的路径
    IFamilySketch2D* pPathSketch = CreateCustomizedProfileBeamPathSketch(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPathSketch, L"pPathSketch为空",L"GDMPLab",L"2024-03-30");
    pPathSketch->SetChildVisible(false);

    // 自定义截面轮廓
    IFamilySketch2D* pProfileSketch = CreateCustomizedProfileBeamProfileSketch(pDoc, pLoop);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pProfileSketch, L"pProfileSketch为空",L"GDMPLab",L"2024-03-30");
    pProfileSketch->SetChildVisible(false);

    // 创建梁体
    IFamilySweep* pBody = IFamilySweep::Create(pDoc, pPathSketch->GetOwnerElementId(), pProfileSketch->GetOwnerElementId(), 0);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pBody, L"pBody为空",L"GDMPLab",L"2024-03-30");

    bool bOk = pDoc->GetRegenerator()->RegenerateDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"族文档生成失败",L"GDMPLab",L"2024-03-30");

    return true;
}

gfam::IFamilySketch2D* gcmp::FamStructureTemplateUtility::CreateCustomizedProfileBeamProfileSketch(IDocument* pDoc, const IPolyCurve* pLoop)
{
    // 左视图参照（与项目创建轮廓视图对应，用于还原曲线三维坐标）
    Coordinate3d refCoord(Vector3d::Zero, Vector3d::NegaUnitY, Vector3d::UnitZ);
    // 横截面草图坐标系(注意：设置YOZ）
    Coordinate3d sketchCoord(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);

    IFamilySketch2D* pSketch = CreateCustomizedProfile(pDoc, refCoord, sketchCoord, pLoop);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSketch, L"创建轮廓失败",L"GDMPLab",L"2024-03-30");

    return pSketch;
}

gfam::IFamilySketch2D* gcmp::FamStructureTemplateUtility::CreateCustomizedProfileBeamPathSketch(IDocument* pDoc)
{
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 创建平面草图
    Coordinate3d coord(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    IFamilySketchPlane* pSketchPlane = IFamilySketchPlane::Create(pDoc, coord);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSketchPlane, L"pSketchPlane为空",L"GDMPLab",L"2024-03-30");

    ElementId sketchPlaneId = pSketchPlane->GetOwnerElementId();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(sketchPlaneId.IsValid(), L"sketchPlaneId无效",L"GDMPLab",L"2024-03-30");

    IFamilySketch2D* pSketch = IFamilySketch2D::Create(pDoc, sketchPlaneId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSketch, L"pSketch为空",L"GDMPLab",L"2024-03-30");

    ElementId sketchId = pSketch->GetOwnerElementId();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(sketchId.IsValid(), L"sketchId无效",L"GDMPLab",L"2024-03-30");
    pSketchPlane->SetSketchId(sketchId);

    // 绘制路径
    IFamily2DSketchLine* pPathLine = IFamily2DSketchLine::Create(pDoc, sketchId, sketchPlaneId, Vector3d::Zero, Vector3d(3000, 0, 0));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPathLine, L"pPathLine为空",L"GDMPLab",L"2024-03-30");

    return pSketch;
}

gfam::IFamilySketch2D* gcmp::FamStructureTemplateUtility::CreateCustomizedProfileColumnProfileSketch(gcmp::IDocument* pDbDoc, const gcmp::IPolyCurve* pLoop)
{
    // 轮廓编辑时的坐标系
    Coordinate3d refCoord(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    // 创建横截面草图的坐标系
    Coordinate3d baseCoord(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    return CreateCustomizedProfile(pDbDoc, refCoord, baseCoord, pLoop);
}

gfam::IFamilySlopedExtrusion* gcmp::FamStructureTemplateUtility::CreateColumnBodyBySlopedExtrusion(gcmp::IDocument* pDbDoc, const gfam::IFamilySketch2D* pSectionSketch)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDbDoc, L"pDbDoc不存在",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSectionSketch, L"横截面草图不存在",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
    const IFamilyParameterDefinition* pHeightParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ColumnHeightBuiltInParameter));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pHeightParamDef, L"柱高度参数不存在",L"GDMPLab",L"2024-03-30");

    // 设置柱高度参数为驱动参数
    pFamilyManager->SetFamilyParameterAsDrive(pHeightParamDef, true);

    // 获得柱高度参数的当前值
    double dColumnHeight = pFamilyManager->GetParameterValueAsDouble(pHeightParamDef);

    // 创建斜拉伸体
    Coordinate3d profileCoord(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    IFamilySlopedExtrusion* pSlopedExtrusion = IFamilySlopedExtrusion::Create(pDbDoc, profileCoord,
        pSectionSketch->GetOwnerElementId(), 0, 0, 0, dColumnHeight);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSlopedExtrusion, L"pSlopedExtrusion为空!",L"GDMPLab",L"2024-03-30");

    // 绑定参数
    IElementParameterBindings* pParameterBinding = pSlopedExtrusion->GetOwnerElement()->GetElementParameters()->GetElementParameterBindings();
    const IFamilyParameterDefinition* pAngleParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ColumnAngleBuiltInParameter));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pAngleParamDef, L"倾斜角度参数不存在",L"GDMPLab",L"2024-03-30");

    pParameterBinding->AddParameterBinding(ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), SlopedExtrusionSectionAngleAroundProfileCoordXBuiltInParameter),
        ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), ColumnAngleBuiltInParameter), pFamilyManager->GetElementId(), false);
    const IFamilyParameterDefinition* pSectionAngleParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(SectionRotateAngleBuiltInParameter));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSectionAngleParamDef, L"倾斜角度参数不存在",L"GDMPLab",L"2024-03-30");

    pFamilyManager->SetFamilyParameterAsDrive(pSectionAngleParamDef, true);
    pParameterBinding->AddParameterBinding(ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), SlopedExtrusionSectionAngleAroundProfileCoordZBuiltInParameter),
        ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), SectionRotateAngleBuiltInParameter), pFamilyManager->GetElementId(), false);

    // ExtrusionLength=高度/cos(倾斜角度)
    std::wstring formula = PARAMETER_DEF(ColumnHeightBuiltInParameter)->GetName() + L"/cos(" + PARAMETER_DEF(ColumnAngleBuiltInParameter)->GetName() + L")";
    //const IFamilyParameterDefinition* pExtrusionLength = pFamilyManager->AddFamilyParameterDefinition(L"ExtrusionLength", FamilyParameterType::Length,
    //    ParameterStorageType::Double, UNIT(Length), PARAMETER_TYPE(None), true, true, formula);

    AddFamilyParameterDefination(pDbDoc, L"ExtrusionLength", FamilyParameterType::Length, true, formula, UNIT(Length), PARAMETER_TYPE(None));

    const IFamilyParameterDefinition* pExtrusionLength = pFamilyManager->GetFamilyParameterDefinition(L"ExtrusionLength");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pExtrusionLength, L"pExtrusionLength为空？",L"GDMPLab",L"2024-03-30");

    pFamilyManager->SetParameterValueAsDouble(pExtrusionLength, dColumnHeight);
    pParameterBinding->AddParameterBinding(ELEMENT_PARAMETER_ID(pSlopedExtrusion->GetOwnerElement(), ExtrusionEndOffsetBuiltInParameter),
        pFamilyManager->GetFamilyParameterDefinitionId(pExtrusionLength->GetElementId()), pFamilyManager->GetElementId(), false);

    return pSlopedExtrusion;
}

gfam::IFamilySketch2D* gcmp::FamStructureTemplateUtility::CreateCustomizedProfile(IDocument* pDoc, const Coordinate3d& refCoord, const Coordinate3d& sketchCoord, const IPolyCurve* pLoop)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pLoop, L"pLoop为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 创建草图平面，用于绘制斜拉伸体的横截面草图
    IFamilySketchPlane* pSketchPlane = IFamilySketchPlane::Create(pDoc, sketchCoord);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSketchPlane, L"pSketchPlane为空",L"GDMPLab",L"2024-03-30");

    ElementId sketchPlaneId = pSketchPlane->GetOwnerElementId();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(sketchPlaneId.IsValid(), L"sketchPlaneId无效",L"GDMPLab",L"2024-03-30");

    IFamilySketch2D* pSketch = IFamilySketch2D::Create(pDoc, sketchPlaneId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSketch, L"pSketch为空",L"GDMPLab",L"2024-03-30");

    ElementId sketchId = pSketch->GetOwnerElementId();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(sketchId.IsValid(), L"sketchId无效",L"GDMPLab",L"2024-03-30");
    pSketchPlane->SetSketchId(sketchId);

    Matrix4d mat;
    refCoord.GetWorldMatrix(mat);

    // 绘制轮廓
    std::vector<OwnerPtr<ICurve2d>> opCurve2dList;
    pLoop->GetAllCurves(opCurve2dList);
    FOR_EACH(opCurve2d, opCurve2dList)
    {
        const ICurve2d* pCurve2d = opCurve2d.get();
        DBG_WARN_AND_CONTINUE_UNLESS(pCurve2d, L"pCurve2d为空",L"GDMPLab",L"2024-03-30");

        GeometryType curve2dType = pCurve2d->GetType();
        if (GeometryType::Line2d == curve2dType)
        {
            const ILine2d* pLine2d = quick_cast<const ILine2d>(pCurve2d);
            Vector3d startPt(pLine2d->GetStartPoint().X(), pLine2d->GetStartPoint().Y(), 0.0);
            Vector3d endPt(pLine2d->GetEndPoint().X(), pLine2d->GetEndPoint().Y(), 0.0);
            Vector3d transStart = Vector3dUtils::TransformVector(startPt, mat);
            Vector3d transEnd = Vector3dUtils::TransformVector(endPt, mat);

            IFamily2DSketchLine* pLine = IFamily2DSketchLine::Create(pDoc, sketchId, sketchPlaneId, transStart, transEnd);
            DBG_WARN_AND_CONTINUE_UNLESS(pLine, L"pLine为空",L"GDMPLab",L"2024-03-30");
        }
        else if (GeometryType::Arc2d == curve2dType)
        {
            const IArc2d* pArc2d = static_cast<const IArc2d*>(pCurve2d);
            Vector3d startPnt(pArc2d->GetStartPoint().X(), pArc2d->GetStartPoint().Y(), 0.0);
            Vector3d endPnt(pArc2d->GetEndPoint().X(), pArc2d->GetEndPoint().Y(), 0.0);
            Vector3d onArcPnt(pArc2d->GetMiddlePoint().X(), pArc2d->GetMiddlePoint().Y(), 0.0);
            Vector3d transStart = Vector3dUtils::TransformVector(startPnt, mat);
            Vector3d transEnd = Vector3dUtils::TransformVector(endPnt, mat);
            Vector3d transOnArc = Vector3dUtils::TransformVector(onArcPnt, mat);

            IFamily2DSketchArc* pArc = IFamily2DSketchArc::Create(pDoc, sketchId, sketchPlaneId, transStart, transEnd, transOnArc);
            DBG_WARN_AND_CONTINUE_UNLESS(pArc, L"pArc为空",L"GDMPLab",L"2024-03-30");
        }
        else if (GeometryType::Ellipse2d == curve2dType)
        {
            const IEllipse2d* pEllipse2d = static_cast<const IEllipse2d*>(pCurve2d);
            Vector3d centerPt(pEllipse2d->GetCenter().X(), pEllipse2d->GetCenter().Y(), 0.0);
            Vector3d majorAxis(pEllipse2d->GetMajorAxis().X(), pEllipse2d->GetMajorAxis().Y(), 0.0);
            double majorRadius = pEllipse2d->GetMajorRadius();
            double minorRadius = pEllipse2d->GetMinorRadius();
            double startAngle = pEllipse2d->GetStartAngle();
            double endAngle = pEllipse2d->GetEndAngle();
            bool anticlockwise = pEllipse2d->IsAntiClockwise();
            Vector3d transCenter = Vector3dUtils::TransformVector(centerPt, mat);
            Vector3d transMajAxis = Vector3dUtils::TransformVector(majorAxis, mat);

            const Coordinate3d& sketchCoord = pSketchPlane->GetPlane();
            IFamily2DSketchEllipse* pEllipse = IFamily2DSketchEllipse::Create(pDoc, sketchId, sketchPlaneId, transCenter, sketchCoord.Z(),
                transMajAxis, majorRadius, minorRadius, startAngle, endAngle, anticlockwise);
            DBG_WARN_AND_CONTINUE_UNLESS(pEllipse, L"pEllipse为空",L"GDMPLab",L"2024-03-30");
        }
        else
        {
            DBG_WARN(L"不支持的线型",L"GDMPLab",L"2024-03-30");
        }
    }

    return pSketch;
}

bool gcmp::FamStructureTemplateUtility::InitRectStripFoundationFamilyDocument(gcmp::IDocument * pDbDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDbDoc, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    const IFamilyParameterDefinition* pCoordDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(CoordinateSystemBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCoordDef != nullptr, L"CoordinateSystemBuiltInParameter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pCoordDef, IParameterValueCurveByPoints::Create());

    //设置放置类型
    const IFamilyParameterDefinition* pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnLevel));

    // 内外面参数
    bool bOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(RectStripFoundationExteriorFaceNodeTag), PARAMETER_UID(ExteriorFaceNodeTagBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");
    bOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(RectStripFoundationInteriorFaceNodeTag), PARAMETER_UID(InteriorFaceNodeTagBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    double profileWidth = 800; // 宽度，类型参数
    bOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(profileWidth), PARAMETER_UID(RectSectionWidthBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    double profileHeight = 400; // 高度，类型参数
    bOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(profileHeight), PARAMETER_UID(RectSectionHeightBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // Z轴定位线
    int zPositioningType = (int)StripFoundationZPositioningType::Top;
    bOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create(zPositioningType), PARAMETER_UID(StripFoundationZPositioningTypeBuiltInParameter), true, false, L"", ParameterProcessType::GeneralInput, FamilyParameterType::Integer);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 底面与上下中心面的偏移值，用于顶面或底面定位
    const std::wstring& zPositioningTypeName = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(StripFoundationZPositioningTypeBuiltInParameter))->GetBasicInformation()->GetName();
    const std::wstring& profileHeightName = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter))->GetBasicInformation()->GetName();
    std::wstring bottomOffsetFormula;
    {
        bottomOffsetFormula = L"(1-" + zPositioningTypeName + L")*" + profileHeightName;
    }
    double bottomOffset(0.0);
    {
        bottomOffset = profileHeight;
    }
    bOk = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(bottomOffset), PARAMETER_UID(StripFoundationBottomOffsetBuiltInParameter), true, true, bottomOffsetFormula, ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    return true;
}

bool gcmp::FamStructureTemplateUtility::AddRectStripFoundationType(gfam::IFamilyManager * pFamilyManager, const std::wstring & familyType, double profileWidth, double profileHeight)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    pFamilyManager->AddFamilyType(familyType);
    pFamilyManager->SetCurrentFamilyType(familyType);

    const IFamilyParameterDefinition* pPDProfileWidth = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionWidthBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPDProfileWidth, L"无法获得截面宽度参数",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pPDProfileWidth, profileWidth);

    const IFamilyParameterDefinition* pPDProfileHeight = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPDProfileHeight, L"无法获得截面高度参数",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pPDProfileHeight, profileHeight);

    return true;
}

bool gcmp::FamStructureTemplateUtility::CreateRectStripFoundationBody(gcmp::IDocument * pDbDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDbDoc, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilySketch2D* pBaseSketch = CreateStripFoundationPath(pDbDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pBaseSketch, L"pBaseSketch为空",L"GDMPLab",L"2024-03-30");

    IFamilySketch2D* pLeftSketch = CreateRectStripFoundationProfile(pDbDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pLeftSketch, L"pLeftSketch为空",L"GDMPLab",L"2024-03-30");

    IFamilySweep* pSweep = IFamilySweep::Create(pDbDoc, pBaseSketch->GetOwnerElementId(), pLeftSketch->GetOwnerElementId(), 0);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSweep, L"pSweep为空!",L"GDMPLab",L"2024-03-30");
    pSweep->GetPathSketch()->SetChildVisible(false);
    pSweep->GetProfileSketch()->SetChildVisible(false);

    bool bOk = pDbDoc->GetRegenerator()->RegenerateDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"族文档生成失败",L"GDMPLab",L"2024-03-30");

    return true;
}

IFamilySketch2D * gcmp::FamStructureTemplateUtility::CreateStripFoundationPath(gcmp::IDocument * pDoc)
{
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 创建平面草图
    Coordinate3d coord(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    IFamilySketchPlane* pSketchPlane = IFamilySketchPlane::Create(pDoc, coord);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSketchPlane, L"pSketchPlane为空",L"GDMPLab",L"2024-03-30");
    ElementId sketchPlaneId = pSketchPlane->GetOwnerElementId();
    IFamilySketch2D* pSketch = IFamilySketch2D::Create(pDoc, sketchPlaneId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSketch, L"pSketch为空",L"GDMPLab",L"2024-03-30");
    ElementId sketchId = pSketch->GetOwnerElementId();
    pSketchPlane->SetSketchId(sketchId);

    // 绘制路径
    IFamily2DSketchLine* pPathLine = IFamily2DSketchLine::Create(pDoc, sketchId, sketchPlaneId, Vector3d::Zero, Vector3d(3000, 0, 0));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPathLine, L"pPathLine为空",L"GDMPLab",L"2024-03-30");

    return pSketch;
}

IFamilySketch2D * gcmp::FamStructureTemplateUtility::CreateRectStripFoundationProfile(gcmp::IDocument * pDoc)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 创建草图平面，用于绘制横截面草图
    Coordinate3d baseCoord(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);
    IFamilySketchPlane* pBaseSketchPlane = IFamilySketchPlane::Create(pDoc, baseCoord);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBaseSketchPlane, L"pBaseSketchPlane为空",L"GDMPLab",L"2024-03-30");
    ElementId baseSketchPlaneId = pBaseSketchPlane->GetOwnerElementId();
    IFamilySketch2D* pBaseSketch = IFamilySketch2D::Create(pDoc, baseSketchPlaneId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBaseSketch, L"pBaseSketch为空",L"GDMPLab",L"2024-03-30");
    ElementId baseSketchId = pBaseSketch->GetOwnerElementId();
    pBaseSketchPlane->SetSketchId(baseSketchId);

    // 绘制轮廓
    double profileWidth = 800;
    double profileHeight = 400;
    IFamily2DSketchLine* pLine[4] = { nullptr, nullptr, nullptr, nullptr }; // 顺时针， 0：矩形顶边
    {
        Vector3d vts[4];
        vts[0] = Vector3d(0, -profileWidth / 2, 0);
        vts[1] = Vector3d(0, profileWidth / 2, 0);
        vts[2] = Vector3d(0, profileWidth / 2, -profileHeight);
        vts[3] = Vector3d(0, -profileWidth / 2, -profileHeight);
        bool bOk = CreateRectangle(pDoc, pBaseSketchPlane, pBaseSketch, vts, pLine);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"CreateRectangle失败",L"GDMPLab",L"2024-03-30");
    }

    {
        // 宽度约束
        Vector3d dimPos(0, 0, profileHeight);
        IFamilyDistanceConstraint* pWidthConstraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, baseSketchId, baseSketchPlaneId, baseCoord,
            pLine[3]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pLine[1]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pWidthConstraint->CalcDimValue();

        const IFamilyParameterDefinition* pWidthParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionWidthBuiltInParameter));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pWidthParameter, L"pWidthParameter为空",L"GDMPLab",L"2024-03-30");
        pWidthConstraint->SetFamilyParameterDefinitionId(pWidthParameter->GetElementId());
    }
    {
        // 高度约束
        Vector3d dimPos(0, profileWidth, 0);
        IFamilyDistanceConstraint* pHeightConstraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, baseSketchId, baseSketchPlaneId, baseCoord,
            pLine[0]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pLine[2]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pHeightConstraint->CalcDimValue();

        const IFamilyParameterDefinition* pHeightParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pHeightParameter, L"pHeightParameter为空",L"GDMPLab",L"2024-03-30");
        pHeightConstraint->SetFamilyParameterDefinitionId(pHeightParameter->GetElementId());
    }
    {
        // 取出内置参照平面
        std::vector<IReferencePlane*> referencePlanes;
        ReferencePlaneUtils::GetVisibleReferencePlanes(pDoc, baseCoord, referencePlanes);
        IReferencePlane* pFrontBackCenterPlane = GetReferencePlane(referencePlanes, FAMILY_FRONT_BACK_CENTER_REFERENCE_PLANE_NAME);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFrontBackCenterPlane, L"pFrontBackCenterPlane为空",L"GDMPLab",L"2024-03-30");

        // 矩形左右边和Z轴的均分约束
        Vector3d frontBackDimPos(0, 0, profileHeight + FamilyTemplateConst::CommonExtend);
        AddEqualDistanceConstraint(pDoc, frontBackDimPos, FamilyTemplateConst::DimScale, baseSketchId, baseSketchPlaneId, baseCoord, pLine[3]->GetOwnerElement(), GraphicsNodeId(1), pBaseSketchPlane->GetOwnerElement(), GraphicsNodeId(1), pLine[1]->GetOwnerElement(), GraphicsNodeId(1));

        // 矩形底边和Y轴的距离约束
        // 注意草图线不要和参照平面加距离约束，而要和草图内的坐标轴加距离约束。
        // 因为草图可能倾斜，此时参照平面不再垂直于草图平面。
        Vector3d bottomOffsetPos(0, profileWidth, profileHeight);
        IFamilyDistanceConstraint* pBottomOffsetConstraint = AddDistanceConstraint(pDoc, bottomOffsetPos, FamilyTemplateConst::DimScale, baseSketchId, baseSketchPlaneId, baseCoord,
            pBaseSketchPlane->GetOwnerElement(), GraphicsNodeId(0), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pLine[2]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pBottomOffsetConstraint->CalcDimValue();

        const IFamilyParameterDefinition* pBotomOffsetParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(StripFoundationBottomOffsetBuiltInParameter));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBotomOffsetParameter, L"pBotomOffsetParameter为空",L"GDMPLab",L"2024-03-30");
        pBottomOffsetConstraint->SetFamilyParameterDefinitionId(pBotomOffsetParameter->GetElementId());
    }

    return pBaseSketch;
}

bool gcmp::FamStructureTemplateUtility::InitTStripFoundationFamilyDocument(gcmp::IDocument * pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    const IFamilyParameterDefinition* pCoordDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(CoordinateSystemBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCoordDef != nullptr, L"CoordinateSystemBuiltInParameter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pCoordDef, IParameterValueCurveByPoints::Create());

    //设置放置类型
    const IFamilyParameterDefinition* pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnLevel));

    // 增加截面类型
    gcmp::EnSectionShapeType sectType = gcmp::SECTION_SHAPE_T;
    bool bRes = AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)sectType), PARAMETER_UID(SectionTypeBuiltInParameter), false, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bRes, L"创建条形基础模板参数有问题",L"GDMPLab",L"2024-03-30");

    // 长度
    double dLength = 4000;
    bRes = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(dLength), PARAMETER_UID(LineFamilyLengthBuiltInParameter), true, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bRes, L"创建墙模板参数有问题",L"GDMPLab",L"2024-03-30");

    double b = 11000, b1 = 400, b2 = 0, h1 = 300, h2 = 300, h3 = 300; // 类型参数
    bool isOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(b), PARAMETER_UID(ProfileBreadthBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(isOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    isOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(b2), PARAMETER_UID(ProfileBreadthOffsetBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(isOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    isOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(b1), PARAMETER_UID(ProfileBreadthPart1BuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(isOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    isOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(h1), PARAMETER_UID(ProfileHeightPart1BuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(isOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    isOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(h2), PARAMETER_UID(ProfileHeightPart2BuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(isOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    isOk = AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(h3), PARAMETER_UID(ProfileHeightPart3BuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(isOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    const IFamilyParameterDefinition* pWidthParamDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileBreadthBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pWidthParamDef != nullptr, L"ProfileBreadthBuiltInParameter参数定义为空",L"GDMPLab",L"2024-03-30");
    ElementId widthParamId = pWidthParamDef->GetElementId();

    isOk = AddTStripFoundationFamilyReferencePlane(pDoc, widthParamId);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(isOk, L"创建参照面失败",L"GDMPLab",L"2024-03-30");

    return true;
}

bool gcmp::FamStructureTemplateUtility::AddTStripFoundationType(gfam::IFamilyManager * pFamilyManager, const std::wstring & familyType, double b, double b1, double b2, double h1, double h2, double h3)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    pFamilyManager->AddFamilyType(familyType);
    pFamilyManager->SetCurrentFamilyType(familyType);

    // b
    const IFamilyParameterDefinition* pBreadth = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileBreadthBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pBreadth, L"pBreadth为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pBreadth, b);

    // h1 (T - 水平端左侧厚度）
    const IFamilyParameterDefinition* pHeight = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileHeightPart1BuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pHeight, L"pHeight为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pHeight, h1);

    // b1 (T - 竖直端厚度）
    const IFamilyParameterDefinition* pBreadth1 = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileBreadthPart1BuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pBreadth1, L"pBreadth1为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pBreadth1, b1);

    // h2 (T - 水平端右侧厚度）
    const IFamilyParameterDefinition* pHeight2 = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileHeightPart2BuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pHeight2, L"pHeight2为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pHeight2, h2);

    // h3 (T - 右高度，T型尾巴右侧长度）
    const IFamilyParameterDefinition* pHeight3 = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileHeightPart3BuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pHeight3, L"pHeight3为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pHeight3, h3);

    // b2
    const IFamilyParameterDefinition* pBreadthOffset = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileBreadthOffsetBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pBreadthOffset, L"pBreadthOffset为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueAsDouble(pBreadthOffset, b2);
    return true;
}

bool gcmp::FamStructureTemplateUtility::CreateTStripFoundationBody(gcmp::IDocument * pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilySketch2D* pBaseSketch = CreateStripFoundationPath(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pBaseSketch, L"pBaseSketch为空",L"GDMPLab",L"2024-03-30");

    IFamilySketch2D* pLeftSketch = CreateModelInvertedTProfile(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pLeftSketch, L"pLeftSketch为空",L"GDMPLab",L"2024-03-30");

    IFamilySweep* pSweep = IFamilySweep::Create(pDoc, pBaseSketch->GetOwnerElementId(), pLeftSketch->GetOwnerElementId(), 0);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSweep, L"pSweep为空!",L"GDMPLab",L"2024-03-30");
    pSweep->GetPathSketch()->SetChildVisible(false);
    pSweep->GetProfileSketch()->SetChildVisible(false);

    bool bOk = pDoc->GetRegenerator()->RegenerateDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"族文档生成失败",L"GDMPLab",L"2024-03-30");

    return true;
}

bool gcmp::FamStructureTemplateUtility::AddTStripFoundationFamilyReferencePlane(gcmp::IDocument * pDoc, gcmp::ElementId widthParamId)
{
    //线式族默认的参考线为从坐标系原点沿着X轴正方向，长度为“线式族长度”族参数标注的长度
    double length = 4000;
    double height = 600;
    double width = 400;
    double rightLength = 2500;
    double bottomLength = 2500;

    //创建一个参照平面，添加标注
    Vector3d startPtY(length, rightLength, 0);
    Vector3d endPtY(length, -rightLength, 0);

    gcmp::IReferencePlane* pReferencePlaneRight = CreateReferencePlaneByPoints(pDoc, startPtY, endPtY, Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pReferencePlaneRight != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneRight->GetBasicInformation()->SetName(FAMILY_RIGHT_REFERENCE_PLANE_NAME);
    pReferencePlaneRight->SetReferencePlaneType(ReferencePlaneType::BuiltIn);
    pReferencePlaneRight->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Right);
    pReferencePlaneRight->SetVisibleUVMin(Vector2d(-rightLength, -height - FamilyTemplateConst::CommonExtend));
    pReferencePlaneRight->SetVisibleUVMax(Vector2d(rightLength, FamilyTemplateConst::CommonExtend));

    gcmp::IReferencePlane* pReferencePlaneBottom = CreateReferencePlaneByPoints(pDoc, Vector3d(0, -bottomLength, -height), Vector3d(0, bottomLength, -height), Vector3d::UnitX);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pReferencePlaneBottom != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneBottom->SetReferencePlaneType(ReferencePlaneType::BuiltIn);
    pReferencePlaneBottom->GetBasicInformation()->SetName(FAMILY_BOTTOM_REFERENCE_PLANE_NAME);
    pReferencePlaneBottom->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Bottom);
    pReferencePlaneBottom->SetVisibleUVMin(Vector2d(-bottomLength, -FamilyTemplateConst::CommonExtend));
    pReferencePlaneBottom->SetVisibleUVMax(Vector2d(bottomLength, length + FamilyTemplateConst::CommonExtend));

    gcmp::IReferencePlane* pReferencePlaneBack = CreateReferencePlaneByPoints(pDoc, Vector3d(-FamilyTemplateConst::CommonExtend, width*0.5, 0), Vector3d(FamilyTemplateConst::CommonExtend, width*0.5, 0), Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pReferencePlaneBack != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneBack->SetReferencePlaneType(ReferencePlaneType::BuiltIn);
    pReferencePlaneBack->GetBasicInformation()->SetName(FAMILY_BACK_REFERENCE_PLANE_NAME);
    pReferencePlaneBack->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Back);
    pReferencePlaneBack->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CommonExtend, -height - FamilyTemplateConst::CommonExtend));
    pReferencePlaneBack->SetVisibleUVMax(Vector2d(length + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend));

    gcmp::IReferencePlane* pReferencePlaneFront = CreateReferencePlaneByPoints(pDoc, Vector3d(-FamilyTemplateConst::CommonExtend, -width*0.5, 0), Vector3d(FamilyTemplateConst::CommonExtend, -width*0.5, 0), Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pReferencePlaneFront != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneFront->SetReferencePlaneType(ReferencePlaneType::BuiltIn);
    pReferencePlaneFront->GetBasicInformation()->SetName(FAMILY_FRONT_REFERENCE_PLANE_NAME);
    pReferencePlaneFront->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Front);
    pReferencePlaneFront->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CommonExtend, -height - FamilyTemplateConst::CommonExtend));
    pReferencePlaneFront->SetVisibleUVMax(Vector2d(length + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend));

    std::vector<IReferencePlane *> allRefPlanes = IReferencePlane::GetAllReferencePlanes(pDoc);
    //获得默认的左右中心
    gcmp::IReferencePlane* pReferencePlaneLeftRightCenter = nullptr;
    gcmp::IReferencePlane* pReferencePlaneTopBottomCenter = nullptr;
    gcmp::IReferencePlane* pReferencePlaneFrontBackCenter = nullptr;

    FOR_EACH(pRefPlane, allRefPlanes)
    {
        if (pRefPlane->GetIsFixed() && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight)
        {
            pReferencePlaneLeftRightCenter = pRefPlane;
        }
        if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack)
        {
            pReferencePlaneFrontBackCenter = pRefPlane;
            pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterExtend, -height - FamilyTemplateConst::CenterExtend));
            pRefPlane->SetVisibleUVMax(Vector2d(length + FamilyTemplateConst::CenterExtend, FamilyTemplateConst::CenterExtend));
        }
        if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfTopBottom)
        {
            pReferencePlaneTopBottomCenter = pRefPlane;
            pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterExtend, -FamilyTemplateConst::CenterLength*0.5));
            pRefPlane->SetVisibleUVMax(Vector2d(length + FamilyTemplateConst::CenterExtend, FamilyTemplateConst::CenterLength*0.5));
        }
    }
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pReferencePlaneLeftRightCenter != nullptr, L"默认的Y参照平面为空",L"GDMPLab",L"2024-03-30");

    gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
    Coordinate3d coordXOY(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    Coordinate3d coordYOZ(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);
    // 创建距离约束
    // 线式族长度约束
    if (pReferencePlaneLeftRightCenter != nullptr)
    {
        Vector3d dimPosition(length / 2, width * 0.5 + FamilyTemplateConst::CenterExtend, 0);
        gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
        gfam::IFamilyDistanceConstraint* pDistanceConstraint = CreateDistanceConstraint(pDoc, dimPosition, FamilyTemplateConst::DimScale, coordXOY
            , pReferencePlaneRight->GetElementId(), GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
            , pReferencePlaneLeftRightCenter->GetElementId(), GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
        pDistanceConstraint->CalcDimValue();

        gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
        const IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(LineFamilyLengthBuiltInParameter));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
        pDistanceConstraint->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
    }

    // 截面宽度
    if (pReferencePlaneFrontBackCenter && widthParamId.IsValid())
    {
        // 截面宽度约束
        Vector3d dimPosition(0, 0, FamilyTemplateConst::CommonExtend);
        gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
        gfam::IFamilyDistanceConstraint* pDistanceConstraintWidth = CreateDistanceConstraint(pDoc, dimPosition, FamilyTemplateConst::DimScale, coordYOZ
            , pReferencePlaneBack->GetElementId(), GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
            , pReferencePlaneFront->GetElementId(), GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
        pDistanceConstraintWidth->CalcDimValue();
        pDistanceConstraintWidth->SetFamilyParameterDefinitionId(widthParamId);

        Vector3d dimPositionEqual(0, 0, -width - FamilyTemplateConst::CommonExtend);
        IFamilyMultiDistanceDimension*pDimEqual = IFamilyMultiDistanceDimension::Create(pDoc, dimPositionEqual, FamilyTemplateConst::DimScale, ElementId(), ElementId(), coordYOZ, true);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pReferencePlaneFront->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pReferencePlaneBack->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

        IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), coordYOZ);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pReferencePlaneFront->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pReferencePlaneBack->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
        pEqualConstraint->SetRatioValue(0.5);

        pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
    }

    return true;
}

void gcmp::FamStructureTemplateUtility::AddWindowParameterDefination(gcmp::IDocument* pDbDoc, double dWall, double dSillH, double dHeight, double dWidth)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");

    bool bThick = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(dWall), PARAMETER_UID(WallThicknessBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    bool bSillH = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(dSillH), PARAMETER_UID(WindowSillHeightBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    bool bDWH = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(dHeight), PARAMETER_UID(DoorOrWindowHeightBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    bool bDWW = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(dWidth), PARAMETER_UID(DoorOrWindowWidthBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);

    DBG_WARN_AND_RETURN_VOID_UNLESS((bThick && bSillH && bDWH && bDWW), L"创建窗模板参数有问题",L"GDMPLab",L"2024-03-30");
}

void gcmp::FamStructureTemplateUtility::AddDoorParameterDefination(gcmp::IDocument* pDbDoc, double wallThickness, double doorHeight, double doorWidth)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");

    bool bWT = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(wallThickness), PARAMETER_UID(WallThicknessBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    bool bDH = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(doorHeight), PARAMETER_UID(DoorOrWindowHeightBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    bool bDW = AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(doorWidth), PARAMETER_UID(DoorOrWindowWidthBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);

    DBG_WARN_AND_RETURN_VOID_UNLESS((bWT && bDH && bDW), L"创建门模板参数有问题",L"GDMPLab",L"2024-03-30");
}

void gcmp::FamStructureTemplateUtility::SetFamParameterType(gcmp::IDocument* pDbDoc, const gcmp::UniIdentity& uid, gfam::FamilyParameterType fpt)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(nullptr != pDbDoc, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(nullptr != pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
    const IFamilyParameterDefinition* pParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(uid);
    DBG_WARN_AND_RETURN_VOID_UNLESS(nullptr != pParameterDefinition, L"pParameterDefinition为空",L"GDMPLab",L"2024-03-30");
    const_cast<IFamilyParameterDefinition*>(pParameterDefinition)->SetParameterType(fpt);
}

gfam::IFamilySketch2D * gcmp::FamStructureTemplateUtility::CreateModelInvertedTProfile(gcmp::IDocument * pDoc)
{
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 创建草图平面，用于绘制横截面草图
    Coordinate3d profileCoord(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);
    IFamilySketchPlane* pProfileSketchPlane = IFamilySketchPlane::Create(pDoc, profileCoord);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pProfileSketchPlane, L"pProfileSketchPlane为空",L"GDMPLab",L"2024-03-30");
    ElementId profileSketchPlaneId = pProfileSketchPlane->GetOwnerElementId();
    IFamilySketch2D* pProfileSketch = IFamilySketch2D::Create(pDoc, profileSketchPlaneId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pProfileSketch, L"pProfileSketch为空",L"GDMPLab",L"2024-03-30");
    ElementId profileSketchId = pProfileSketch->GetOwnerElementId();
    pProfileSketchPlane->SetSketchId(profileSketchId);

    std::vector<IReferencePlane*> referencePlanes = IReferencePlane::GetAllReferencePlanes(pDoc);
    // 取出内置参照平面
    IReferencePlane* pTopBottomCenterPlane = GetReferencePlane(referencePlanes, FAMILY_TOP_BOTTOM_CENTER_REFERENCE_PLANE_NAME);
    IReferencePlane* pFrontBackCenterPlane = GetReferencePlane(referencePlanes, FAMILY_FRONT_BACK_CENTER_REFERENCE_PLANE_NAME);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pTopBottomCenterPlane && pFrontBackCenterPlane, L"pTopBottomCenterPlane && pFrontBackCenterPlane为空",L"GDMPLab",L"2024-03-30");
    // 前后中心线
    IFamily2DSketchLine* pFrontBackCenterLocationLine2 = nullptr;
    {
        pFrontBackCenterLocationLine2 = IFamily2DSketchLine::CreateAsReference(pDoc, profileSketchId, profileSketchPlaneId, Vector3d::Zero, Vector3d(0, 0, -1000));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFrontBackCenterLocationLine2, L"pFrontBackCenterLocationLine为空",L"GDMPLab",L"2024-03-30");
        pFrontBackCenterLocationLine2->GetOwnerElement()->GetBasicInformation()->SetName(GBMP_TR(L"前后中心定位线"));
        // 第二前后中心线约束
        FamilyConstraintUtils::AddConstraint(pDoc, FamilyConstraintType::Parallel, pFrontBackCenterPlane->GetElementId(), FamilyConstraintReferenceType::Self, pFrontBackCenterLocationLine2->GetOwnerElementId(), FamilyConstraintReferenceType::Self, pProfileSketchPlane, pProfileSketch);

        // 给两条中心线添加长度约束，防止在旋转时变长
        Vector3d dimPos(-500, 0, 0);
        double scale = 500.0;
        IFamilyDistanceConstraint* pLengthConstraint = AddDistanceConstraint(pDoc, dimPos, scale, profileSketchId, profileSketchPlaneId, profileCoord,
            pFrontBackCenterLocationLine2->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::StartPoint,
            pFrontBackCenterLocationLine2->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::EndPoint);
        pLengthConstraint->CalcDimValue();
    }

    // 绘制轮廓，中心点在b中心位置
    //                 Z
    //                 ↑
    //           v[5]_______v[4]
    //              |       |
    //           h3-|       |
    //v[7]__________|v[6]   |
    //   |                  |_______
    //   |               v[3]       |v[2]
    //h2-|                          |
    //   |                          |-h1
    //   |                          |
    //   |_________(0,0,0)__________|
    //  v[0](0,-500,0)           v[1](0,500,0)--->Y

    double b = 1000, b1 = 400, b2 = 0, h1 = 300, h2 = 300, h3 = 300;
    Vector3d vts[8];
    vts[0] = Vector3d(0, -b / 2, 0);
    vts[1] = Vector3d(0, b / 2, 0);
    vts[2] = Vector3d(0, b / 2, h1);
    vts[3] = Vector3d(0, b2 + b1 / 2, h1);
    vts[4] = Vector3d(0, b2 + b1 / 2, h2 + h3);
    vts[5] = Vector3d(0, b2 - b1 / 2, h2 + h3);
    vts[6] = Vector3d(0, b2 - b1 / 2, h2);
    vts[7] = Vector3d(0, -b / 2, h2);
    IFamily2DSketchLine* pLine[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
    CreateProfileT(pDoc, pProfileSketchPlane, pProfileSketch, vts, pLine);


    {
        // 顶边与轮廓草图水平坐标轴对齐约束
        OwnerPtr<IGraphicsNodeReference> refY = IGraphicsNodeReference::Create(profileSketchPlaneId, GraphicsNodeId(0), GraphicsNodeReferenceType::GraphicsNodeSelf);
        OwnerPtr<IGraphicsNodeReference> refBottomLine = IGraphicsNodeReference::Create(pLine[0]->GetOwnerElementId(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry, *refY, *refBottomLine, profileSketchPlaneId, profileSketchId);
    }

    {
        // b约束
        Vector3d dimPos(0, 0, 400);
        IFamilyDistanceConstraint* pBreadthConstraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, profileSketchId, profileSketchPlaneId, profileCoord,
            pLine[7]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pLine[1]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pBreadthConstraint->CalcDimValue();

        const IFamilyParameterDefinition* pBreadthParameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileBreadthBuiltInParameter));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBreadthParameter, L"pBreadthParameter为空",L"GDMPLab",L"2024-03-30");
        pBreadthConstraint->SetFamilyParameterDefinitionId(pBreadthParameter->GetElementId());
    }
    {
        // h1约束
        Vector3d dimPos(0, -500, -300);
        IFamilyDistanceConstraint* pHeight1Constraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, profileSketchId, profileSketchPlaneId, profileCoord,
            pLine[0]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pLine[6]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pHeight1Constraint->CalcDimValue();

        const IFamilyParameterDefinition* pHeight1Parameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileHeightPart1BuiltInParameter));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pHeight1Parameter, L"pHeight1Parameter为空",L"GDMPLab",L"2024-03-30");
        pHeight1Constraint->SetFamilyParameterDefinitionId(pHeight1Parameter->GetElementId());
    }
    {
        // b1约束
        Vector3d dimPos(0, 0, -800);
        IFamilyDistanceConstraint* pBreadth1Constraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, profileSketchId, profileSketchPlaneId, profileCoord,
            pLine[5]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pLine[3]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pBreadth1Constraint->CalcDimValue();

        const IFamilyParameterDefinition* pBreadth1Parameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileBreadthPart1BuiltInParameter));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBreadth1Parameter, L"pBreadth1Parameter为空",L"GDMPLab",L"2024-03-30");
        pBreadth1Constraint->SetFamilyParameterDefinitionId(pBreadth1Parameter->GetElementId());
    }
    {
        // h2约束
        Vector3d dimPos(0, 400, -100);
        IFamilyDistanceConstraint* pHeight2Constraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, profileSketchId, profileSketchPlaneId, profileCoord,
            pLine[0]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pLine[2]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pHeight2Constraint->CalcDimValue();

        const IFamilyParameterDefinition* pHeight2Parameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileHeightPart2BuiltInParameter));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pHeight2Parameter, L"pHeight2Parameter为空",L"GDMPLab",L"2024-03-30");
        pHeight2Constraint->SetFamilyParameterDefinitionId(pHeight2Parameter->GetElementId());
    }

    {
        // h3约束
        Vector3d dimPos(0, 400, -100);
        IFamilyDistanceConstraint* pHeight3Constraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, profileSketchId, profileSketchPlaneId, profileCoord,
            pLine[2]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pLine[4]->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pHeight3Constraint->CalcDimValue();

        const IFamilyParameterDefinition* pHeight3Parameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileHeightPart3BuiltInParameter));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pHeight3Parameter, L"pHeightFParameter为空",L"GDMPLab",L"2024-03-30");
        pHeight3Constraint->SetFamilyParameterDefinitionId(pHeight3Parameter->GetElementId());
    }

    {
        // 左右均分约束
        Vector3d dimPos(0, 0, 500);
        AddEqualDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, profileSketchId, profileSketchPlaneId, profileCoord, pLine[1]->GetOwnerElement(), GraphicsNodeId(1), pFrontBackCenterPlane, GraphicsNodeId(1), pLine[7]->GetOwnerElement(), GraphicsNodeId(1));
        AddEqualDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, profileSketchId, profileSketchPlaneId, profileCoord, pLine[3]->GetOwnerElement(), GraphicsNodeId(1), pFrontBackCenterLocationLine2->GetOwnerElement(), GraphicsNodeId(1), pLine[5]->GetOwnerElement(), GraphicsNodeId(1));
    }

    {
        // b2约束
        Vector3d dimPos(-200, -500, 0);
        IFamilyDistanceConstraint* pBreadth2Constraint = AddDistanceConstraint(pDoc, dimPos, FamilyTemplateConst::DimScale, profileSketchId, profileSketchPlaneId, profileCoord,
            pFrontBackCenterPlane, GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf,
            pFrontBackCenterLocationLine2->GetOwnerElement(), GraphicsNodeId(1), GraphicsNodeReferenceType::GraphicsNodeSelf);
        pBreadth2Constraint->CalcDimValue();

        const IFamilyParameterDefinition* pBreadth2Parameter = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ProfileBreadthOffsetBuiltInParameter));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBreadth2Parameter, L"pBreadth1Parameter为空",L"GDMPLab",L"2024-03-30");
        pBreadth2Constraint->SetFamilyParameterDefinitionId(pBreadth2Parameter->GetElementId());
        pBreadth2Constraint->FinishEditing();
    }

    return pProfileSketch;
}

void FamStructureTemplateUtility::CreateAndAddRectangle(gcmp::IDocument* pDoc, const gfam::IFamilySketchPlane* pSketchPlane, const gfam::IFamilySketch2D* pSketch, const gcmp::Vector3d vts[4], gfam::IFamily2DSketchLine* pFamLine[4])
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pSketchPlane != nullptr, L"pSketchPlane为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pSketch != nullptr, L"pSketch为空",L"GDMPLab",L"2024-03-30");

    ElementId sketchModelId;
    sketchModelId = pSketch->GetOwnerElementId();
    ElementId sketchPlaneModelId;
    sketchPlaneModelId = pSketchPlane->GetOwnerElementId();
    //绘制矩形
    ElementId savedModelLineId;
    {
        ElementId firstCurveID;
        ElementId preCurveID;

        for (int i = 0; i < 4; ++i)
        {
            pFamLine[i] = IFamily2DSketchLine::Create(pDoc, sketchModelId, sketchPlaneModelId, vts[i], vts[(i + 1) % 4]);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamLine[i] != nullptr, L"Create FamLine1 failed! ",L"GDMPLab",L"2024-03-30");
            savedModelLineId = pFamLine[i]->GetOwnerElementId();

            if (i > 0) // 增加端点重合约束
            {
                gfam::FamilyConstraintUtils::AddConstraintAsCoincidentPoints(pDoc, preCurveID, FamilyConstraintReferenceType::End, savedModelLineId, FamilyConstraintReferenceType::Start, pSketchPlane, pSketch);
                if (i == 3)
                {
                    gfam::FamilyConstraintUtils::AddConstraintAsCoincidentPoints(pDoc, savedModelLineId, FamilyConstraintReferenceType::End, firstCurveID, FamilyConstraintReferenceType::Start, pSketchPlane, pSketch);
                    break;
                }
            }
            else
            {
                firstCurveID = savedModelLineId;
            }
            preCurveID = savedModelLineId;
        }
    }
}

//草图外用的
//返回值可能为nullptr
gfam::IFamilyDistanceConstraint* FamStructureTemplateUtility::CreateDistanceConstraint(
    IDocument* pDoc
    , const Vector3d& dimPos
    , double dimScale
    , const gcmp::Coordinate3d& coord
    , const ElementId& refId1
    , gcmp::GraphicsNodeReferenceType  refType1
    , const gcmp::GraphicsNodeId& leafTag1
    , const ElementId& refId2
    , gcmp::GraphicsNodeReferenceType  refType2
    , const gcmp::GraphicsNodeId& leafTag2
    , gfam::IFamilyMultiDistanceDimension*& pDimBind
)
{
    DBG_WARN_AND_RETURN_UNLESS(nullptr != pDoc, nullptr, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    IFamilyMultiDistanceDimension* pDim = IFamilyMultiDistanceDimension::Create(pDoc, dimPos, dimScale, ElementId(), ElementId(), coord, false);
    DBG_WARN_AND_RETURN_UNLESS(nullptr != pDim, nullptr, L"无法创建FamilyMultiDistanceDimension",L"GDMPLab",L"2024-03-30");
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(refId1, leafTag1, refType1);
    pDim->AddReferenceObject(TransferOwnership(opRef1));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(refId2, leafTag2, refType2);
    pDim->AddReferenceObject(TransferOwnership(opRef2));

    IFamilyDistanceConstraint* pDistanceConstraint = IFamilyDistanceConstraint::Create(pDoc, ElementId(), ElementId(), pDim->GetOwnerElementId(), coord);
    DBG_WARN_AND_RETURN_UNLESS(nullptr != pDistanceConstraint, nullptr, L"无法创建FamilyDistanceConstraint",L"GDMPLab",L"2024-03-30");
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(refId1, leafTag1, refType1);
    pDistanceConstraint->AddReferenceObject(TransferOwnership(opRef3));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef4 = IGraphicsNodeReference::Create(refId2, leafTag2, refType2);
    pDistanceConstraint->AddReferenceObject(TransferOwnership(opRef4));
    pDim->AddConstraintObject(pDistanceConstraint->GetOwnerElementId());
    pDimBind = pDim;
    return pDistanceConstraint;
}

//草图外用的
//返回值可能为nullptr
gfam::IFamilyGeometryConstraint* FamStructureTemplateUtility::CreateEqualConstraint(
    IDocument* pDoc
    , const gcmp::Coordinate3d& coord
    , IElement* pEle1
    , gcmp::GraphicsNodeReferenceType  refType1
    , const gcmp::GraphicsNodeId& leafTag1
    , IElement* pEle2
    , gcmp::GraphicsNodeReferenceType  refType2
    , const gcmp::GraphicsNodeId& leafTag2
)
{
    DBG_WARN_AND_RETURN_UNLESS(nullptr != pDoc, nullptr, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyGeometryConstraint* pEqualConstraint = IFamilyAlignConstraint::Create(pDoc, ElementId::InvalidID, ElementCreationOptions::Normal);
    DBG_WARN_AND_RETURN_UNLESS(nullptr != pEqualConstraint, nullptr, L"无法创建pEqualConstraint",L"GDMPLab",L"2024-03-30");
    pEqualConstraint->SetCoordinate(coord);

    gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pEle1->GetElementId(), leafTag1, refType1);
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef1));

    gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pEle2->GetElementId(), leafTag2, refType2);
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef2));

    return pEqualConstraint;
}
